(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / mcs / class.cs
blobf793c3d1f5bff7bcc956f87cb0bc72c6f6956eb7
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Licensed under the terms of the GNU GPL
9 //
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.
32 #define CACHE
33 using System;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
40 using System.Security;
41 using System.Security.Permissions;
42 using System.Text;
44 using Mono.CompilerServices.SymbolWriter;
46 namespace Mono.CSharp {
48 public enum Kind {
49 Root,
50 Struct,
51 Class,
52 Interface
55 /// <summary>
56 /// This is the base class for structs and classes.
57 /// </summary>
58 public abstract class TypeContainer : DeclSpace, IMemberContainer {
60 public class MemberCoreArrayList: ArrayList
62 /// <summary>
63 /// Defines the MemberCore objects that are in this array
64 /// </summary>
65 public virtual void DefineContainerMembers ()
67 foreach (MemberCore mc in this) {
68 mc.Define ();
72 public virtual void Emit ()
74 foreach (MemberCore mc in this)
75 mc.Emit ();
79 public class MethodArrayList: MemberCoreArrayList
81 [Flags]
82 enum CachedMethods {
83 Equals = 1,
84 GetHashCode = 1 << 1
87 CachedMethods cached_method;
88 TypeContainer container;
90 public MethodArrayList (TypeContainer container)
92 this.container = container;
95 /// <summary>
96 /// Method container contains Equals method
97 /// </summary>
98 public bool HasEquals {
99 set {
100 cached_method |= CachedMethods.Equals;
103 get {
104 return (cached_method & CachedMethods.Equals) != 0;
108 /// <summary>
109 /// Method container contains GetHashCode method
110 /// </summary>
111 public bool HasGetHashCode {
112 set {
113 cached_method |= CachedMethods.GetHashCode;
116 get {
117 return (cached_method & CachedMethods.GetHashCode) != 0;
121 public override void DefineContainerMembers ()
123 base.DefineContainerMembers ();
125 if ((RootContext.WarningLevel >= 3) && HasEquals && !HasGetHashCode) {
126 Report.Warning (659, container.Location, "'{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
132 public sealed class IndexerArrayList: MemberCoreArrayList
134 /// <summary>
135 /// The indexer name for this container
136 /// </summary>
137 public string IndexerName = DefaultIndexerName;
139 bool seen_normal_indexers = false;
141 TypeContainer container;
143 public IndexerArrayList (TypeContainer container)
145 this.container = container;
148 /// <summary>
149 /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
150 /// class is consistent. Either it is `Item' or it is the name defined by all the
151 /// indexers with the `IndexerName' attribute.
153 /// Turns out that the IndexerNameAttribute is applied to each indexer,
154 /// but it is never emitted, instead a DefaultMember attribute is attached
155 /// to the class.
156 /// </summary>
157 public override void DefineContainerMembers()
159 base.DefineContainerMembers ();
161 string class_indexer_name = null;
164 // If there's both an explicit and an implicit interface implementation, the
165 // explicit one actually implements the interface while the other one is just
166 // a normal indexer. See bug #37714.
169 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
170 foreach (Indexer i in this) {
171 if (i.InterfaceType != null) {
172 if (seen_normal_indexers)
173 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
174 continue;
177 seen_normal_indexers = true;
179 if (class_indexer_name == null) {
180 class_indexer_name = i.ShortName;
181 continue;
184 if (i.ShortName != class_indexer_name)
185 Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
188 if (class_indexer_name != null)
189 IndexerName = class_indexer_name;
192 public override void Emit ()
194 base.Emit ();
196 if (!seen_normal_indexers)
197 return;
199 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
200 container.TypeBuilder.SetCustomAttribute (cb);
204 public class OperatorArrayList: MemberCoreArrayList
206 TypeContainer container;
208 public OperatorArrayList (TypeContainer container)
210 this.container = container;
214 // Operator pair checking
216 class OperatorEntry
218 public int flags;
219 public Type ret_type;
220 public Type type1, type2;
221 public Operator op;
222 public Operator.OpType ot;
224 public OperatorEntry (int f, Operator o)
226 flags = f;
228 ret_type = o.OperatorMethod.ReturnType;
229 Type [] pt = o.OperatorMethod.ParameterTypes;
230 type1 = pt [0];
231 type2 = pt [1];
232 op = o;
233 ot = o.OperatorType;
236 public override int GetHashCode ()
238 return ret_type.GetHashCode ();
241 public override bool Equals (object o)
243 OperatorEntry other = (OperatorEntry) o;
245 if (other.ret_type != ret_type)
246 return false;
247 if (other.type1 != type1)
248 return false;
249 if (other.type2 != type2)
250 return false;
251 return true;
256 // Checks that some operators come in pairs:
257 // == and !=
258 // > and <
259 // >= and <=
260 // true and false
262 // They are matched based on the return type and the argument types
264 void CheckPairedOperators ()
266 Hashtable pairs = new Hashtable (null, null);
267 Operator true_op = null;
268 Operator false_op = null;
269 bool has_equality_or_inequality = false;
271 // Register all the operators we care about.
272 foreach (Operator op in this){
273 int reg = 0;
275 switch (op.OperatorType){
276 case Operator.OpType.Equality:
277 reg = 1;
278 has_equality_or_inequality = true;
279 break;
280 case Operator.OpType.Inequality:
281 reg = 2;
282 has_equality_or_inequality = true;
283 break;
285 case Operator.OpType.True:
286 true_op = op;
287 break;
288 case Operator.OpType.False:
289 false_op = op;
290 break;
292 case Operator.OpType.GreaterThan:
293 reg = 1; break;
294 case Operator.OpType.LessThan:
295 reg = 2; break;
297 case Operator.OpType.GreaterThanOrEqual:
298 reg = 1; break;
299 case Operator.OpType.LessThanOrEqual:
300 reg = 2; break;
302 if (reg == 0)
303 continue;
305 OperatorEntry oe = new OperatorEntry (reg, op);
307 object o = pairs [oe];
308 if (o == null)
309 pairs [oe] = oe;
310 else {
311 oe = (OperatorEntry) o;
312 oe.flags |= reg;
316 if (true_op != null){
317 if (false_op == null)
318 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
319 } else if (false_op != null)
320 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
323 // Look for the mistakes.
325 foreach (DictionaryEntry de in pairs){
326 OperatorEntry oe = (OperatorEntry) de.Key;
328 if (oe.flags == 3)
329 continue;
331 string s = "";
332 switch (oe.ot){
333 case Operator.OpType.Equality:
334 s = "!=";
335 break;
336 case Operator.OpType.Inequality:
337 s = "==";
338 break;
339 case Operator.OpType.GreaterThan:
340 s = "<";
341 break;
342 case Operator.OpType.LessThan:
343 s = ">";
344 break;
345 case Operator.OpType.GreaterThanOrEqual:
346 s = "<=";
347 break;
348 case Operator.OpType.LessThanOrEqual:
349 s = ">=";
350 break;
352 Report.Error (216, oe.op.Location,
353 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
356 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
357 if (container.Methods == null || !container.Methods.HasEquals)
358 Report.Warning (660, container.Location, "'{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
360 if (container.Methods == null || !container.Methods.HasGetHashCode)
361 Report.Warning (661, container.Location, "'{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
365 public override void DefineContainerMembers ()
367 base.DefineContainerMembers ();
368 CheckPairedOperators ();
373 // Whether this is a struct, class or interface
374 public readonly Kind Kind;
376 // Holds a list of classes and structures
377 ArrayList types;
379 // Holds the list of properties
380 MemberCoreArrayList properties;
382 // Holds the list of enumerations
383 MemberCoreArrayList enums;
385 // Holds the list of delegates
386 MemberCoreArrayList delegates;
388 // Holds the list of constructors
389 protected MemberCoreArrayList instance_constructors;
391 // Holds the list of fields
392 MemberCoreArrayList fields;
394 // Holds a list of fields that have initializers
395 protected ArrayList initialized_fields;
397 // Holds a list of static fields that have initializers
398 protected ArrayList initialized_static_fields;
400 // Holds the list of constants
401 MemberCoreArrayList constants;
403 // Holds the list of
404 MemberCoreArrayList interfaces;
406 // Holds the methods.
407 MethodArrayList methods;
409 // Holds the events
410 protected MemberCoreArrayList events;
412 // Holds the indexers
413 IndexerArrayList indexers;
415 // Holds the operators
416 MemberCoreArrayList operators;
418 // Holds the iterators
419 ArrayList iterators;
421 // Holds the parts of a partial class;
422 ArrayList parts;
424 // The emit context for toplevel objects.
425 EmitContext ec;
427 public EmitContext EmitContext {
428 get { return ec; }
432 // Pointers to the default constructor and the default static constructor
434 protected Constructor default_constructor;
435 protected Constructor default_static_constructor;
438 // Whether we have at least one non-static field
440 bool have_nonstatic_fields = false;
443 // This one is computed after we can distinguish interfaces
444 // from classes from the arraylist `type_bases'
446 string base_class_name;
447 public Type base_class_type;
449 ArrayList type_bases;
451 bool members_defined;
452 bool members_defined_ok;
454 // The interfaces we implement.
455 TypeExpr [] ifaces;
456 protected Type[] base_inteface_types;
458 // The parent member container and our member cache
459 IMemberContainer parent_container;
460 MemberCache member_cache;
462 public const string DefaultIndexerName = "Item";
464 public TypeContainer (NamespaceEntry ns, TypeContainer parent, MemberName name,
465 Attributes attrs, Kind kind, Location l)
466 : base (ns, parent, name, attrs, l)
468 this.Kind = kind;
470 types = new ArrayList ();
472 base_class_name = null;
475 public bool AddToMemberContainer (MemberCore symbol, bool is_method)
477 return AddToContainer (symbol, is_method, String.Concat (Name, '.', symbol.Name), symbol.Name);
480 bool AddToTypeContainer (DeclSpace ds)
482 return AddToContainer (ds, false, ds.Name, ds.Basename);
485 public void AddConstant (Const constant)
487 if (!AddToMemberContainer (constant, false))
488 return;
490 if (constants == null)
491 constants = new MemberCoreArrayList ();
493 constants.Add (constant);
496 public void AddEnum (Mono.CSharp.Enum e)
498 if (!AddToTypeContainer (e))
499 return;
501 if (enums == null)
502 enums = new MemberCoreArrayList ();
504 enums.Add (e);
507 public void AddClassOrStruct (TypeContainer c)
509 if (!AddToTypeContainer (c))
510 return;
512 types.Add (c);
515 public void AddDelegate (Delegate d)
517 if (!AddToTypeContainer (d))
518 return;
520 if (delegates == null)
521 delegates = new MemberCoreArrayList ();
523 delegates.Add (d);
526 public void AddMethod (Method method)
528 if (!AddToMemberContainer (method, true))
529 return;
531 if (methods == null)
532 methods = new MethodArrayList (this);
534 if (method.Name.IndexOf ('.') != -1)
535 methods.Insert (0, method);
536 else
537 methods.Add (method);
540 public void AddConstructor (Constructor c)
542 if (c.Name != Basename) {
543 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
546 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
548 if (is_static){
549 if (default_static_constructor != null) {
550 Report.SymbolRelatedToPreviousError (default_static_constructor);
551 Report.Error (111, c.Location, Error111, Name, c.Name);
552 return;
555 default_static_constructor = c;
556 } else {
557 if (c.IsDefault ()){
558 if (default_constructor != null) {
559 Report.SymbolRelatedToPreviousError (default_constructor);
560 Report.Error (111, c.Location, Error111, c.Location, Name, c.Name);
561 return;
563 default_constructor = c;
566 if (instance_constructors == null)
567 instance_constructors = new MemberCoreArrayList ();
569 instance_constructors.Add (c);
573 internal static string Error111 {
574 get {
575 return "Type '{0}' already defines a member called '{1}' with the same parameter types";
579 public void AddInterface (TypeContainer iface)
581 if (!AddToTypeContainer (iface))
582 return;
584 if (interfaces == null) {
585 interfaces = new MemberCoreArrayList ();
588 interfaces.Add (iface);
591 public void AddField (Field field)
593 if (!AddToMemberContainer (field, false))
594 return;
596 if (fields == null)
597 fields = new MemberCoreArrayList ();
599 fields.Add (field);
601 if (field.HasInitializer){
602 if ((field.ModFlags & Modifiers.STATIC) != 0){
603 if (initialized_static_fields == null)
604 initialized_static_fields = new ArrayList ();
606 initialized_static_fields.Add (field);
607 } else {
608 if (initialized_fields == null)
609 initialized_fields = new ArrayList ();
611 initialized_fields.Add (field);
615 if ((field.ModFlags & Modifiers.STATIC) == 0)
616 have_nonstatic_fields = true;
619 public void AddProperty (Property prop)
621 if (!AddToMemberContainer (prop, false) ||
622 !AddToMemberContainer (prop.Get, true) || !AddToMemberContainer (prop.Set, true))
623 return;
625 if (properties == null)
626 properties = new MemberCoreArrayList ();
628 if (prop.Name.IndexOf ('.') != -1)
629 properties.Insert (0, prop);
630 else
631 properties.Add (prop);
634 public void AddEvent (Event e)
636 if (!AddToMemberContainer (e, false))
637 return;
639 if (e is EventProperty) {
640 if (!AddToMemberContainer (e.Add, true))
641 return;
643 if (!AddToMemberContainer (e.Remove, true))
644 return;
647 if (events == null)
648 events = new MemberCoreArrayList ();
650 events.Add (e);
654 /// <summary>
655 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
656 /// </summary>
657 public void AddIndexer (Indexer i)
659 if (indexers == null)
660 indexers = new IndexerArrayList (this);
662 if (i.IsExplicitImpl)
663 indexers.Insert (0, i);
664 else
665 indexers.Add (i);
668 public void AddOperator (Operator op)
670 if (!AddToMemberContainer (op, true))
671 return;
673 if (operators == null)
674 operators = new OperatorArrayList (this);
676 operators.Add (op);
679 public void AddIterator (Iterator i)
681 if (iterators == null)
682 iterators = new ArrayList ();
684 iterators.Add (i);
687 public void AddType (TypeContainer tc)
689 types.Add (tc);
692 public void AddPart (ClassPart part)
694 if (parts == null)
695 parts = new ArrayList ();
697 parts.Add (part);
700 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
702 if (a.Type == TypeManager.default_member_type) {
703 if (Indexers != null) {
704 Report.Error (646, a.Location,
705 "Cannot specify the DefaultMember attribute on" +
706 " a type containing an indexer");
707 return;
711 base.ApplyAttributeBuilder (a, cb);
714 public override AttributeTargets AttributeTargets {
715 get {
716 throw new NotSupportedException ();
720 public ArrayList Types {
721 get {
722 return types;
726 public MethodArrayList Methods {
727 get {
728 return methods;
732 public ArrayList Constants {
733 get {
734 return constants;
738 public ArrayList Interfaces {
739 get {
740 return interfaces;
744 public ArrayList Iterators {
745 get {
746 return iterators;
750 public string Base {
751 get {
752 return base_class_name;
756 public ArrayList Bases {
757 get {
758 return type_bases;
761 set {
762 type_bases = value;
766 public ArrayList Fields {
767 get {
768 return fields;
772 public ArrayList InstanceConstructors {
773 get {
774 return instance_constructors;
778 public ArrayList Properties {
779 get {
780 return properties;
784 public ArrayList Events {
785 get {
786 return events;
790 public ArrayList Enums {
791 get {
792 return enums;
796 public ArrayList Indexers {
797 get {
798 return indexers;
802 public ArrayList Operators {
803 get {
804 return operators;
808 public ArrayList Delegates {
809 get {
810 return delegates;
814 public ArrayList Parts {
815 get {
816 return parts;
820 public virtual TypeAttributes TypeAttr {
821 get {
822 return Modifiers.TypeAttr (ModFlags, this);
826 public string IndexerName {
827 get {
828 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
833 // Emits the instance field initializers
835 public bool EmitFieldInitializers (EmitContext ec)
837 ArrayList fields;
838 Expression instance_expr;
840 if (ec.IsStatic){
841 fields = initialized_static_fields;
842 instance_expr = null;
843 } else {
844 fields = initialized_fields;
845 instance_expr = new This (Location.Null).Resolve (ec);
848 if (fields == null)
849 return true;
851 foreach (Field f in fields){
852 Expression e = f.GetInitializerExpression (ec);
853 if (e == null)
854 return false;
856 Location l = f.Location;
857 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
858 fe.InstanceExpression = instance_expr;
859 ExpressionStatement a = new Assign (fe, e, l);
861 a = a.ResolveStatement (ec);
862 if (a == null)
863 return false;
865 a.EmitStatement (ec);
868 return true;
872 // Defines the default constructors
874 protected void DefineDefaultConstructor (bool is_static)
876 Constructor c;
878 // The default constructor is public
879 // If the class is abstract, the default constructor is protected
880 // The default static constructor is private
882 int mods = Modifiers.PUBLIC;
883 if (is_static)
884 mods = Modifiers.STATIC | Modifiers.PRIVATE;
885 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
886 mods = Modifiers.PROTECTED;
888 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
889 new ConstructorBaseInitializer (
890 null, Parameters.EmptyReadOnlyParameters,
891 Location),
892 Location);
894 AddConstructor (c);
896 c.Block = new ToplevelBlock (null, Location);
900 /// <remarks>
901 /// The pending methods that need to be implemented
902 // (interfaces or abstract methods)
903 /// </remarks>
904 public PendingImplementation Pending;
906 public abstract void Register ();
908 public abstract PendingImplementation GetPendingImplementations ();
910 TypeExpr[] GetPartialBases (out TypeExpr parent, out bool error)
912 ArrayList ifaces = new ArrayList ();
914 parent = null;
915 Location parent_loc = Location.Null;
917 foreach (ClassPart part in parts) {
918 TypeExpr new_parent;
919 TypeExpr[] new_ifaces;
921 new_ifaces = part.GetClassBases (out new_parent, out error);
922 if (error)
923 return null;
925 if ((parent != null) && (new_parent != null) &&
926 !parent.Equals (new_parent)) {
927 Report.Error (263, part.Location,
928 "Partial declarations of `{0}' must " +
929 "not specify different base classes",
930 Name);
932 if (!Location.IsNull (parent_loc))
933 Report.LocationOfPreviousError (parent_loc);
935 error = true;
936 return null;
939 if ((parent == null) && (new_parent != null)) {
940 parent = new_parent;
941 parent_loc = part.Location;
944 if (new_ifaces == null)
945 continue;
947 foreach (TypeExpr iface in new_ifaces) {
948 bool found = false;
949 foreach (TypeExpr old_iface in ifaces) {
950 if (old_iface.Equals (iface)) {
951 found = true;
952 break;
956 if (!found)
957 ifaces.Add (iface);
961 error = false;
963 TypeExpr[] retval = new TypeExpr [ifaces.Count];
964 ifaces.CopyTo (retval, 0);
965 return retval;
968 TypeExpr[] GetNormalBases (out TypeExpr parent, out bool error)
970 parent = null;
972 int count = Bases.Count;
973 int start, i, j;
975 if (Kind == Kind.Class){
976 TypeExpr name = ResolveTypeExpr (
977 (Expression) Bases [0], false, Location);
979 if (name == null){
980 error = true;
981 return null;
984 if (name.IsClass){
985 parent = name;
986 start = 1;
987 } else {
988 start = 0;
990 } else {
991 start = 0;
994 TypeExpr [] ifaces = new TypeExpr [count-start];
996 for (i = start, j = 0; i < count; i++, j++){
997 Expression name = (Expression) Bases [i];
998 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
999 if (resolved == null) {
1000 error = true;
1001 return null;
1004 ifaces [j] = resolved;
1007 error = false;
1008 return ifaces;
1011 /// <summary>
1012 /// This function computes the Base class and also the
1013 /// list of interfaces that the class or struct @c implements.
1014 ///
1015 /// The return value is an array (might be null) of
1016 /// interfaces implemented (as Types).
1017 ///
1018 /// The @parent argument is set to the parent object or null
1019 /// if this is `System.Object'.
1020 /// </summary>
1021 TypeExpr [] GetClassBases (out TypeExpr parent, out bool error)
1023 int i;
1025 error = false;
1027 TypeExpr[] ifaces;
1029 if (parts != null)
1030 ifaces = GetPartialBases (out parent, out error);
1031 else if (Bases == null){
1032 parent = null;
1033 return null;
1034 } else
1035 ifaces = GetNormalBases (out parent, out error);
1037 if (error)
1038 return null;
1040 if ((parent != null) && (Kind == Kind.Class)){
1041 if (parent.IsSealed){
1042 error = true;
1043 Report.SymbolRelatedToPreviousError (parent.Type);
1044 if (parent.Type.IsAbstract) {
1045 Report.Error (709, Location, "'{0}': Cannot derive from static class", GetSignatureForError ());
1046 } else {
1047 Report.Error (509, Location, "'{0}': Cannot derive from sealed class", GetSignatureForError ());
1049 return null;
1052 if (!parent.CanInheritFrom ()){
1053 Report.Error (644, Location,
1054 "`{0}' cannot inherit from special class `{1}'",
1055 Name, parent.Name);
1056 error = true;
1057 return null;
1060 if (!parent.AsAccessible (this, ModFlags))
1061 Report.Error (60, Location,
1062 "Inconsistent accessibility: base class `" +
1063 parent.Name + "' is less accessible than class `" +
1064 Name + "'");
1067 if (parent != null)
1068 base_class_name = parent.Name;
1070 if (ifaces == null)
1071 return null;
1073 int count = ifaces != null ? ifaces.Length : 0;
1075 for (i = 0; i < count; i++) {
1076 TypeExpr iface = (TypeExpr) ifaces [i];
1078 if ((Kind != Kind.Class) && !iface.IsInterface){
1079 string what = Kind == Kind.Struct ?
1080 "Struct" : "Interface";
1082 Report.Error (527, Location,
1083 "In {0} `{1}', type `{2}' is not "+
1084 "an interface", what, Name, iface.Name);
1085 error = true;
1086 return null;
1089 if (iface.IsClass) {
1090 if (parent != null){
1091 Report.Error (527, Location,
1092 "In Class `{0}', `{1}' is not " +
1093 "an interface", Name, iface.Name);
1094 error = true;
1095 return null;
1099 for (int x = 0; x < i; x++) {
1100 if (iface.Equals (ifaces [x])) {
1101 Report.Error (528, Location,
1102 "`{0}' is already listed in " +
1103 "interface list", iface.Name);
1104 error = true;
1105 return null;
1109 if ((Kind == Kind.Interface) &&
1110 !iface.AsAccessible (Parent, ModFlags))
1111 Report.Error (61, Location,
1112 "Inconsistent accessibility: base " +
1113 "interface `{0}' is less accessible " +
1114 "than interface `{1}'", iface.Name,
1115 Name);
1118 return TypeManager.ExpandInterfaces (ifaces);
1121 bool error = false;
1124 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1126 public override TypeBuilder DefineType ()
1128 TypeExpr parent;
1130 if (TypeBuilder != null)
1131 return TypeBuilder;
1133 if (error)
1134 return null;
1136 if (InTransit) {
1137 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
1138 error = true;
1139 return null;
1142 InTransit = true;
1144 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
1146 ifaces = GetClassBases (out parent, out error);
1147 if (error)
1148 return null;
1150 if (parent == null) {
1151 if (Kind == Kind.Class){
1152 if (RootContext.StdLib)
1153 parent = TypeManager.system_object_expr;
1154 else if (Name != "System.Object")
1155 parent = TypeManager.system_object_expr;
1156 } else if (Kind == Kind.Struct) {
1158 // If we are compiling our runtime,
1159 // and we are defining ValueType, then our
1160 // parent is `System.Object'.
1162 if (!RootContext.StdLib && Name == "System.ValueType")
1163 parent = TypeManager.system_object_expr;
1164 else
1165 parent = TypeManager.system_valuetype_expr;
1169 if ((Kind == Kind.Struct) && TypeManager.value_type == null)
1170 throw new Exception ();
1172 TypeAttributes type_attributes = TypeAttr;
1174 if (parent != null) {
1175 base_class_type = parent.ResolveType (ec);
1176 if (base_class_type == null) {
1177 error = true;
1178 return null;
1182 try {
1183 if (IsTopLevel){
1184 if (TypeManager.NamespaceClash (Name, Location)) {
1185 error = true;
1186 return null;
1189 ModuleBuilder builder = CodeGen.Module.Builder;
1190 TypeBuilder = builder.DefineType (
1191 Name, type_attributes, base_class_type, null);
1193 } else {
1194 TypeBuilder builder = Parent.DefineType ();
1195 if (builder == null)
1196 return null;
1198 TypeBuilder = builder.DefineNestedType (
1199 Basename, type_attributes, base_class_type, null);
1202 catch (ArgumentException) {
1203 Report.RuntimeMissingSupport (Location, "static classes");
1204 return null;
1208 // Structs with no fields need to have at least one byte.
1209 // The right thing would be to set the PackingSize in a DefineType
1210 // but there are no functions that allow interfaces *and* the size to
1211 // be specified.
1214 if ((Kind == Kind.Struct) && !have_nonstatic_fields){
1215 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
1216 FieldAttributes.Private);
1219 // add interfaces that were not added at type creation
1220 if (ifaces != null) {
1221 base_inteface_types = new Type[ifaces.Length];
1222 for (int i = 0; i < ifaces.Length; ++i) {
1223 Type itype = ifaces [i].ResolveType (ec);
1224 if (itype == null) {
1225 error = true;
1226 continue;
1228 TypeBuilder.AddInterfaceImplementation (itype);
1229 base_inteface_types [i] = itype;
1232 if (error)
1233 return null;
1237 // Finish the setup for the EmitContext
1239 ec.ContainerType = TypeBuilder;
1241 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
1243 if ((parent != null) && parent.IsAttribute) {
1244 RootContext.RegisterAttribute (this);
1245 } else if (!(this is Iterator))
1246 RootContext.RegisterOrder (this);
1248 if (!DefineNestedTypes ()) {
1249 error = true;
1250 return null;
1253 InTransit = false;
1254 return TypeBuilder;
1257 protected virtual bool DefineNestedTypes ()
1259 if (Interfaces != null) {
1260 foreach (TypeContainer iface in Interfaces)
1261 if (iface.DefineType () == null)
1262 return false;
1265 if (Types != null) {
1266 foreach (TypeContainer tc in Types)
1267 if (tc.DefineType () == null)
1268 return false;
1271 if (Delegates != null) {
1272 foreach (Delegate d in Delegates)
1273 if (d.DefineType () == null)
1274 return false;
1277 if (Enums != null) {
1278 foreach (Enum en in Enums)
1279 if (en.DefineType () == null)
1280 return false;
1283 if (Parts != null) {
1284 foreach (ClassPart part in Parts) {
1285 part.TypeBuilder = TypeBuilder;
1286 part.base_class_type = base_class_type;
1287 part.ec = new EmitContext (part, Mono.CSharp.Location.Null, null, null, ModFlags);
1291 return true;
1294 static void Error_KeywordNotAllowed (Location loc)
1296 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1299 /// <summary>
1300 /// Populates our TypeBuilder with fields and methods
1301 /// </summary>
1302 public override bool DefineMembers (TypeContainer container)
1304 if (members_defined)
1305 return members_defined_ok;
1307 members_defined_ok = DoDefineMembers ();
1308 members_defined = true;
1310 return members_defined_ok;
1313 bool DoDefineMembers ()
1316 // We need to be able to use the member cache while we are checking/defining
1318 if (TypeBuilder.BaseType != null)
1319 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1321 if (TypeBuilder.IsInterface)
1322 parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
1324 if (IsTopLevel) {
1325 if ((ModFlags & Modifiers.NEW) != 0)
1326 Error_KeywordNotAllowed (Location);
1327 } else {
1328 // HACK: missing implemenation
1329 // This is not fully functional. Better way how to handle this is to have recursive definition of containers
1330 // instead of flat as we have now.
1331 // Now we are not able to check inner attribute class because its parent had not been defined.
1333 // TODO: remove this if
1334 if (Parent.MemberCache != null) {
1335 MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
1336 if (conflict_symbol == null) {
1337 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1338 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1339 } else {
1340 if ((ModFlags & Modifiers.NEW) == 0) {
1341 Report.SymbolRelatedToPreviousError (conflict_symbol);
1342 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError ());
1348 DefineContainerMembers (constants);
1349 DefineContainerMembers (fields);
1351 if ((Kind == Kind.Class) && !(this is ClassPart) && !(this is StaticClass)){
1352 if ((instance_constructors == null) &&
1353 !(this is StaticClass)) {
1354 if (default_constructor == null)
1355 DefineDefaultConstructor (false);
1358 if (initialized_static_fields != null &&
1359 default_static_constructor == null)
1360 DefineDefaultConstructor (true);
1363 if (Kind == Kind.Struct){
1365 // Structs can not have initialized instance
1366 // fields
1368 if (initialized_static_fields != null &&
1369 default_static_constructor == null)
1370 DefineDefaultConstructor (true);
1372 if (initialized_fields != null)
1373 ReportStructInitializedInstanceError ();
1376 Pending = GetPendingImplementations ();
1378 if (parts != null) {
1379 foreach (ClassPart part in parts) {
1380 if (!part.DefineMembers (this))
1381 return false;
1386 // Constructors are not in the defined_names array
1388 DefineContainerMembers (instance_constructors);
1390 if (default_static_constructor != null)
1391 default_static_constructor.Define ();
1393 DefineContainerMembers (properties);
1394 DefineContainerMembers (events);
1395 DefineContainerMembers (indexers);
1396 DefineContainerMembers (methods);
1397 DefineContainerMembers (operators);
1398 DefineContainerMembers (enums);
1399 DefineContainerMembers (delegates);
1401 #if CACHE
1402 if (!(this is ClassPart))
1403 member_cache = new MemberCache (this, false);
1404 #endif
1406 if (parts != null) {
1407 foreach (ClassPart part in parts)
1408 part.member_cache = member_cache;
1411 if (iterators != null) {
1412 foreach (Iterator iterator in iterators) {
1413 if (iterator.DefineType () == null)
1414 return false;
1417 foreach (Iterator iterator in iterators) {
1418 if (!iterator.DefineMembers (this))
1419 return false;
1423 return true;
1426 void ReportStructInitializedInstanceError ()
1428 string n = TypeBuilder.FullName;
1430 foreach (Field f in initialized_fields){
1431 Report.Error (
1432 573, Location,
1433 "`" + n + "." + f.Name + "': can not have " +
1434 "instance field initializers in structs");
1438 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1440 if (mcal != null)
1441 mcal.DefineContainerMembers ();
1444 public override bool Define ()
1446 if (parts != null) {
1447 foreach (ClassPart part in parts) {
1448 if (!part.Define ())
1449 return false;
1453 return true;
1456 public MemberInfo FindMemberWithSameName (string name, bool ignore_methods)
1458 return ParentContainer.MemberCache.FindMemberWithSameName (name, ignore_methods, null);
1461 /// <summary>
1462 /// This function is based by a delegate to the FindMembers routine
1463 /// </summary>
1464 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1466 return true;
1469 /// <summary>
1470 /// This filter is used by FindMembers, and we just keep
1471 /// a global for the filter to `AlwaysAccept'
1472 /// </summary>
1473 static MemberFilter accepting_filter;
1476 static TypeContainer ()
1478 accepting_filter = new MemberFilter (AlwaysAccept);
1481 public MethodInfo[] GetMethods ()
1483 ArrayList members = new ArrayList ();
1485 DefineMembers (null);
1487 if (methods != null) {
1488 int len = methods.Count;
1489 for (int i = 0; i < len; i++) {
1490 Method m = (Method) methods [i];
1492 members.Add (m.MethodBuilder);
1496 if (operators != null) {
1497 int len = operators.Count;
1498 for (int i = 0; i < len; i++) {
1499 Operator o = (Operator) operators [i];
1501 members.Add (o.OperatorMethodBuilder);
1505 if (properties != null) {
1506 int len = properties.Count;
1507 for (int i = 0; i < len; i++) {
1508 Property p = (Property) properties [i];
1510 if (p.GetBuilder != null)
1511 members.Add (p.GetBuilder);
1512 if (p.SetBuilder != null)
1513 members.Add (p.SetBuilder);
1517 if (indexers != null) {
1518 int len = indexers.Count;
1519 for (int i = 0; i < len; i++) {
1520 Indexer ix = (Indexer) indexers [i];
1522 if (ix.GetBuilder != null)
1523 members.Add (ix.GetBuilder);
1524 if (ix.SetBuilder != null)
1525 members.Add (ix.SetBuilder);
1529 if (events != null) {
1530 int len = events.Count;
1531 for (int i = 0; i < len; i++) {
1532 Event e = (Event) events [i];
1534 if (e.AddBuilder != null)
1535 members.Add (e.AddBuilder);
1536 if (e.RemoveBuilder != null)
1537 members.Add (e.RemoveBuilder);
1541 MethodInfo[] retMethods = new MethodInfo [members.Count];
1542 members.CopyTo (retMethods, 0);
1543 return retMethods;
1546 // Indicated whether container has StructLayout attribute set Explicit
1547 public virtual bool HasExplicitLayout {
1548 get {
1549 return false;
1553 /// <summary>
1554 /// This method returns the members of this type just like Type.FindMembers would
1555 /// Only, we need to use this for types which are _being_ defined because MS'
1556 /// implementation can't take care of that.
1557 /// </summary>
1559 // FIXME: return an empty static array instead of null, that cleans up
1560 // some code and is consistent with some coding conventions I just found
1561 // out existed ;-)
1564 // Notice that in various cases we check if our field is non-null,
1565 // something that would normally mean that there was a bug elsewhere.
1567 // The problem happens while we are defining p-invoke methods, as those
1568 // will trigger a FindMembers, but this happens before things are defined
1570 // Since the whole process is a no-op, it is fine to check for null here.
1572 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1573 MemberFilter filter, object criteria)
1575 ArrayList members = null;
1577 int modflags = 0;
1578 if ((bf & BindingFlags.Public) != 0)
1579 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1580 Modifiers.INTERNAL;
1581 if ((bf & BindingFlags.NonPublic) != 0)
1582 modflags |= Modifiers.PRIVATE;
1584 int static_mask = 0, static_flags = 0;
1585 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1586 case BindingFlags.Static:
1587 static_mask = static_flags = Modifiers.STATIC;
1588 break;
1590 case BindingFlags.Instance:
1591 static_mask = Modifiers.STATIC;
1592 static_flags = 0;
1593 break;
1595 default:
1596 static_mask = static_flags = 0;
1597 break;
1600 Timer.StartTimer (TimerType.TcFindMembers);
1602 if (filter == null)
1603 filter = accepting_filter;
1605 if ((mt & MemberTypes.Field) != 0) {
1606 if (fields != null) {
1607 int len = fields.Count;
1608 for (int i = 0; i < len; i++) {
1609 Field f = (Field) fields [i];
1611 if ((f.ModFlags & modflags) == 0)
1612 continue;
1613 if ((f.ModFlags & static_mask) != static_flags)
1614 continue;
1616 FieldBuilder fb = f.FieldBuilder;
1617 if (fb != null && filter (fb, criteria) == true) {
1618 if (members == null)
1619 members = new ArrayList ();
1621 members.Add (fb);
1626 if (constants != null) {
1627 int len = constants.Count;
1628 for (int i = 0; i < len; i++) {
1629 Const con = (Const) constants [i];
1631 if ((con.ModFlags & modflags) == 0)
1632 continue;
1633 if ((con.ModFlags & static_mask) != static_flags)
1634 continue;
1636 FieldBuilder fb = con.FieldBuilder;
1637 if (fb != null && filter (fb, criteria) == true) {
1638 if (members == null)
1639 members = new ArrayList ();
1641 members.Add (fb);
1647 if ((mt & MemberTypes.Method) != 0) {
1648 if (methods != null) {
1649 int len = methods.Count;
1650 for (int i = 0; i < len; i++) {
1651 Method m = (Method) methods [i];
1653 if ((m.ModFlags & modflags) == 0)
1654 continue;
1655 if ((m.ModFlags & static_mask) != static_flags)
1656 continue;
1658 MethodBuilder mb = m.MethodBuilder;
1660 if (mb != null && filter (mb, criteria) == true) {
1661 if (members == null)
1662 members = new ArrayList ();
1664 members.Add (mb);
1669 if (operators != null) {
1670 int len = operators.Count;
1671 for (int i = 0; i < len; i++) {
1672 Operator o = (Operator) operators [i];
1674 if ((o.ModFlags & modflags) == 0)
1675 continue;
1676 if ((o.ModFlags & static_mask) != static_flags)
1677 continue;
1679 MethodBuilder ob = o.OperatorMethodBuilder;
1680 if (ob != null && filter (ob, criteria) == true) {
1681 if (members == null)
1682 members = new ArrayList ();
1684 members.Add (ob);
1689 if (properties != null) {
1690 int len = properties.Count;
1691 for (int i = 0; i < len; i++) {
1692 Property p = (Property) properties [i];
1694 if ((p.ModFlags & modflags) == 0)
1695 continue;
1696 if ((p.ModFlags & static_mask) != static_flags)
1697 continue;
1699 MethodBuilder b;
1701 b = p.GetBuilder;
1702 if (b != null && filter (b, criteria) == true) {
1703 if (members == null)
1704 members = new ArrayList ();
1706 members.Add (b);
1709 b = p.SetBuilder;
1710 if (b != null && filter (b, criteria) == true) {
1711 if (members == null)
1712 members = new ArrayList ();
1714 members.Add (b);
1719 if (indexers != null) {
1720 int len = indexers.Count;
1721 for (int i = 0; i < len; i++) {
1722 Indexer ix = (Indexer) indexers [i];
1724 if ((ix.ModFlags & modflags) == 0)
1725 continue;
1726 if ((ix.ModFlags & static_mask) != static_flags)
1727 continue;
1729 MethodBuilder b;
1731 b = ix.GetBuilder;
1732 if (b != null && filter (b, criteria) == true) {
1733 if (members == null)
1734 members = new ArrayList ();
1736 members.Add (b);
1739 b = ix.SetBuilder;
1740 if (b != null && filter (b, criteria) == true) {
1741 if (members == null)
1742 members = new ArrayList ();
1744 members.Add (b);
1750 if ((mt & MemberTypes.Event) != 0) {
1751 if (events != null) {
1752 int len = events.Count;
1753 for (int i = 0; i < len; i++) {
1754 Event e = (Event) events [i];
1756 if ((e.ModFlags & modflags) == 0)
1757 continue;
1758 if ((e.ModFlags & static_mask) != static_flags)
1759 continue;
1761 MemberInfo eb = e.EventBuilder;
1762 if (eb != null && filter (eb, criteria) == true) {
1763 if (members == null)
1764 members = new ArrayList ();
1766 members.Add (e.EventBuilder);
1772 if ((mt & MemberTypes.Property) != 0){
1773 if (properties != null) {
1774 int len = properties.Count;
1775 for (int i = 0; i < len; i++) {
1776 Property p = (Property) properties [i];
1778 if ((p.ModFlags & modflags) == 0)
1779 continue;
1780 if ((p.ModFlags & static_mask) != static_flags)
1781 continue;
1783 MemberInfo pb = p.PropertyBuilder;
1784 if (pb != null && filter (pb, criteria) == true) {
1785 if (members == null)
1786 members = new ArrayList ();
1788 members.Add (p.PropertyBuilder);
1793 if (indexers != null) {
1794 int len = indexers.Count;
1795 for (int i = 0; i < len; i++) {
1796 Indexer ix = (Indexer) indexers [i];
1798 if ((ix.ModFlags & modflags) == 0)
1799 continue;
1800 if ((ix.ModFlags & static_mask) != static_flags)
1801 continue;
1803 MemberInfo ib = ix.PropertyBuilder;
1804 if (ib != null && filter (ib, criteria) == true) {
1805 if (members == null)
1806 members = new ArrayList ();
1808 members.Add (ix.PropertyBuilder);
1814 if ((mt & MemberTypes.NestedType) != 0) {
1815 if (types != null) {
1816 int len = types.Count;
1817 for (int i = 0; i < len; i++) {
1818 TypeContainer t = (TypeContainer) types [i];
1820 if ((t.ModFlags & modflags) == 0)
1821 continue;
1823 TypeBuilder tb = t.TypeBuilder;
1824 if (tb != null && (filter (tb, criteria) == true)) {
1825 if (members == null)
1826 members = new ArrayList ();
1828 members.Add (tb);
1833 if (enums != null) {
1834 int len = enums.Count;
1835 for (int i = 0; i < len; i++) {
1836 Enum en = (Enum) enums [i];
1838 if ((en.ModFlags & modflags) == 0)
1839 continue;
1841 TypeBuilder tb = en.TypeBuilder;
1842 if (tb != null && (filter (tb, criteria) == true)) {
1843 if (members == null)
1844 members = new ArrayList ();
1846 members.Add (tb);
1851 if (delegates != null) {
1852 int len = delegates.Count;
1853 for (int i = 0; i < len; i++) {
1854 Delegate d = (Delegate) delegates [i];
1856 if ((d.ModFlags & modflags) == 0)
1857 continue;
1859 TypeBuilder tb = d.TypeBuilder;
1860 if (tb != null && (filter (tb, criteria) == true)) {
1861 if (members == null)
1862 members = new ArrayList ();
1864 members.Add (tb);
1869 if (interfaces != null) {
1870 int len = interfaces.Count;
1871 for (int i = 0; i < len; i++) {
1872 TypeContainer iface = (TypeContainer) interfaces [i];
1874 if ((iface.ModFlags & modflags) == 0)
1875 continue;
1877 TypeBuilder tb = iface.TypeBuilder;
1878 if (tb != null && (filter (tb, criteria) == true)) {
1879 if (members == null)
1880 members = new ArrayList ();
1882 members.Add (tb);
1888 if ((mt & MemberTypes.Constructor) != 0){
1889 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1890 int len = instance_constructors.Count;
1891 for (int i = 0; i < len; i++) {
1892 Constructor c = (Constructor) instance_constructors [i];
1894 ConstructorBuilder cb = c.ConstructorBuilder;
1895 if (cb != null && filter (cb, criteria) == true) {
1896 if (members == null)
1897 members = new ArrayList ();
1899 members.Add (cb);
1904 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1905 ConstructorBuilder cb =
1906 default_static_constructor.ConstructorBuilder;
1908 if (cb != null && filter (cb, criteria) == true) {
1909 if (members == null)
1910 members = new ArrayList ();
1912 members.Add (cb);
1918 // Lookup members in parent if requested.
1920 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1921 if (TypeBuilder.BaseType != null) {
1922 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1923 if (list.Count > 0) {
1924 if (members == null)
1925 members = new ArrayList ();
1927 members.AddRange (list);
1930 if (base_inteface_types != null) {
1931 foreach (Type base_type in base_inteface_types) {
1932 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1934 if (list.Count > 0) {
1935 if (members == null)
1936 members = new ArrayList ();
1937 members.AddRange (list);
1943 Timer.StopTimer (TimerType.TcFindMembers);
1945 if (members == null)
1946 return MemberList.Empty;
1947 else
1948 return new MemberList (members);
1951 public override MemberCache MemberCache {
1952 get {
1953 return member_cache;
1957 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1958 MemberFilter filter, object criteria)
1960 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1962 if (ds != null)
1963 return ds.FindMembers (mt, bf, filter, criteria);
1964 else
1965 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1970 // FindMethods will look for methods not only in the type `t', but in
1971 // any interfaces implemented by the type.
1973 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1974 MemberFilter filter, object criteria)
1976 return null;
1979 /// <summary>
1980 /// Emits the values for the constants
1981 /// </summary>
1982 public void EmitConstants ()
1984 if (constants != null)
1985 foreach (Const con in constants)
1986 con.Emit ();
1987 return;
1990 protected virtual void VerifyMembers (EmitContext ec)
1993 // Check for internal or private fields that were never assigned
1995 if (RootContext.WarningLevel >= 3) {
1996 if (fields != null){
1997 foreach (Field f in fields) {
1998 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1999 continue;
2001 if ((f.status & Field.Status.USED) == 0){
2002 Report.Warning (169, f.Location, "The private field '{0}' is never used", f.GetSignatureForError ());
2003 continue;
2007 // Only report 649 on level 4
2009 if (RootContext.WarningLevel < 4)
2010 continue;
2012 if ((f.status & Field.Status.ASSIGNED) != 0)
2013 continue;
2015 Report.Warning (649, f.Location, "Field '{0}' is never assigned to, and will always have its default value '{1}'", f.GetSignatureForError (), "");
2021 /// <summary>
2022 /// Emits the code, this step is performed after all
2023 /// the types, enumerations, constructors
2024 /// </summary>
2025 public void EmitType ()
2027 if (OptAttributes != null)
2028 OptAttributes.Emit (ec, this);
2030 Emit ();
2032 if (instance_constructors != null) {
2033 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsCompliaceRequired (this)) {
2034 bool has_compliant_args = false;
2036 foreach (Constructor c in instance_constructors) {
2037 c.Emit ();
2039 if (has_compliant_args)
2040 continue;
2042 has_compliant_args = c.HasCompliantArgs;
2044 if (!has_compliant_args)
2045 Report.Error (3015, Location, "'{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2046 } else {
2047 foreach (Constructor c in instance_constructors)
2048 c.Emit ();
2052 EmitConstants ();
2054 if (default_static_constructor != null)
2055 default_static_constructor.Emit ();
2057 if (methods != null)
2058 foreach (Method m in methods)
2059 m.Emit ();
2061 if (operators != null)
2062 foreach (Operator o in operators)
2063 o.Emit ();
2065 if (properties != null)
2066 foreach (Property p in properties)
2067 p.Emit ();
2069 if (indexers != null){
2070 indexers.Emit ();
2073 if (fields != null)
2074 foreach (Field f in fields)
2075 f.Emit ();
2077 if (events != null){
2078 foreach (Event e in Events)
2079 e.Emit ();
2082 if (delegates != null) {
2083 foreach (Delegate d in Delegates) {
2084 d.Emit ();
2088 if (enums != null) {
2089 foreach (Enum e in enums) {
2090 e.Emit ();
2094 if (parts != null) {
2095 foreach (ClassPart part in parts)
2096 part.EmitType ();
2099 if ((Pending != null) && !(this is ClassPart))
2100 if (Pending.VerifyPendingMethods ())
2101 return;
2103 VerifyMembers (ec);
2105 if (iterators != null)
2106 foreach (Iterator iterator in iterators)
2107 iterator.EmitType ();
2109 // if (types != null)
2110 // foreach (TypeContainer tc in types)
2111 // tc.Emit ();
2114 public override void CloseType ()
2116 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2117 return;
2119 try {
2120 caching_flags |= Flags.CloseTypeCreated;
2121 TypeBuilder.CreateType ();
2122 } catch (TypeLoadException){
2124 // This is fine, the code still created the type
2126 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2127 // Console.WriteLine (e.Message);
2128 } catch {
2129 Console.WriteLine ("In type: " + Name);
2130 throw;
2133 if (Enums != null)
2134 foreach (Enum en in Enums)
2135 en.CloseType ();
2137 if (Types != null){
2138 foreach (TypeContainer tc in Types)
2139 if (tc.Kind == Kind.Struct)
2140 tc.CloseType ();
2142 foreach (TypeContainer tc in Types)
2143 if (tc.Kind != Kind.Struct)
2144 tc.CloseType ();
2147 if (Delegates != null)
2148 foreach (Delegate d in Delegates)
2149 d.CloseType ();
2151 if (Iterators != null)
2152 foreach (Iterator i in Iterators)
2153 i.CloseType ();
2155 types = null;
2156 properties = null;
2157 enums = null;
2158 delegates = null;
2159 fields = null;
2160 initialized_fields = null;
2161 initialized_static_fields = null;
2162 constants = null;
2163 interfaces = null;
2164 methods = null;
2165 events = null;
2166 indexers = null;
2167 operators = null;
2168 iterators = null;
2169 ec = null;
2170 default_constructor = null;
2171 default_static_constructor = null;
2172 type_bases = null;
2173 OptAttributes = null;
2174 ifaces = null;
2175 parent_container = null;
2176 member_cache = null;
2179 // TODO: make it obsolete and use GetSignatureForError
2180 public string MakeName (string n)
2182 return "`" + Name + "." + n + "'";
2186 // Performs the validation on a Method's modifiers (properties have
2187 // the same properties).
2189 public bool MethodModifiersValid (int flags, string n, Location loc)
2191 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2192 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2193 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2194 bool ok = true;
2197 // At most one of static, virtual or override
2199 if ((flags & Modifiers.STATIC) != 0){
2200 if ((flags & vao) != 0){
2201 Report.Error (
2202 112, loc, "static method " + MakeName (n) + "can not be marked " +
2203 "as virtual, abstract or override");
2204 ok = false;
2208 if (Kind == Kind.Struct){
2209 if ((flags & va) != 0){
2210 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2211 ok = false;
2215 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2216 Report.Error (
2217 113, loc, MakeName (n) +
2218 " marked as override cannot be marked as new or virtual");
2219 ok = false;
2223 // If the declaration includes the abstract modifier, then the
2224 // declaration does not include static, virtual or extern
2226 if ((flags & Modifiers.ABSTRACT) != 0){
2227 if ((flags & Modifiers.EXTERN) != 0){
2228 Report.Error (
2229 180, loc, MakeName (n) + " can not be both abstract and extern");
2230 ok = false;
2233 if ((flags & Modifiers.VIRTUAL) != 0){
2234 Report.Error (
2235 503, loc, MakeName (n) + " can not be both abstract and virtual");
2236 ok = false;
2239 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2240 Report.Error (
2241 513, loc, MakeName (n) +
2242 " is abstract but its container class is not");
2243 ok = false;
2248 if ((flags & Modifiers.PRIVATE) != 0){
2249 if ((flags & vao) != 0){
2250 Report.Error (
2251 621, loc, MakeName (n) +
2252 " virtual or abstract members can not be private");
2253 ok = false;
2257 if ((flags & Modifiers.SEALED) != 0){
2258 if ((flags & Modifiers.OVERRIDE) == 0){
2259 Report.Error (
2260 238, loc, MakeName (n) +
2261 " cannot be sealed because it is not an override");
2262 ok = false;
2266 return ok;
2269 public bool UserDefinedStaticConstructor {
2270 get {
2271 return default_static_constructor != null;
2275 protected override bool VerifyClsCompliance (DeclSpace ds)
2277 if (!base.VerifyClsCompliance (ds))
2278 return false;
2280 VerifyClsName ();
2282 // parent_container is null for System.Object
2283 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2284 Report.Error (3009, Location, "'{0}': base type '{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2286 return true;
2290 /// <summary>
2291 /// Checks whether container name is CLS Compliant
2292 /// </summary>
2293 void VerifyClsName ()
2295 Hashtable parent_members = parent_container == null ?
2296 new Hashtable () :
2297 parent_container.MemberCache.GetPublicMembers ();
2298 Hashtable this_members = new Hashtable ();
2300 foreach (DictionaryEntry entry in defined_names) {
2301 MemberCore mc = (MemberCore)entry.Value;
2302 if (!mc.IsClsCompliaceRequired (this))
2303 continue;
2305 string name = (string)entry.Key;
2306 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2308 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2309 object found = parent_members [lcase];
2310 if (found == null) {
2311 found = this_members [lcase];
2312 if (found == null) {
2313 this_members.Add (lcase, mc);
2314 continue;
2318 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2319 continue;
2321 if (found is MemberInfo) {
2322 if (basename == ((MemberInfo)found).Name)
2323 continue;
2324 Report.SymbolRelatedToPreviousError ((MemberInfo)found);
2325 } else {
2326 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2328 Report.Error (3005, mc.Location, "Identifier '{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2333 /// <summary>
2334 /// Performs checks for an explicit interface implementation. First it
2335 /// checks whether the `interface_type' is a base inteface implementation.
2336 /// Then it checks whether `name' exists in the interface type.
2337 /// </summary>
2338 public virtual bool VerifyImplements (Type interface_type, string full,
2339 string name, Location loc)
2341 bool found = false;
2343 if (ifaces != null){
2344 foreach (TypeExpr t in ifaces){
2345 if (t.Type == interface_type){
2346 found = true;
2347 break;
2352 if (!found){
2353 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2354 return false;
2357 return true;
2360 protected override void VerifyObsoleteAttribute()
2362 CheckUsageOfObsoleteAttribute (base_class_type);
2364 if (ifaces == null)
2365 return;
2367 foreach (TypeExpr expr in ifaces) {
2368 CheckUsageOfObsoleteAttribute (expr.Type);
2374 // IMemberContainer
2377 string IMemberContainer.Name {
2378 get {
2379 return Name;
2383 Type IMemberContainer.Type {
2384 get {
2385 return TypeBuilder;
2389 MemberCache IMemberContainer.MemberCache {
2390 get {
2391 return member_cache;
2395 bool IMemberContainer.IsInterface {
2396 get {
2397 return Kind == Kind.Interface;
2401 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2403 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
2406 public virtual IMemberContainer ParentContainer {
2407 get {
2408 return parent_container;
2413 public class PartialContainer : TypeContainer {
2415 public readonly Namespace Namespace;
2416 public readonly int OriginalModFlags;
2417 public readonly int AllowedModifiers;
2418 public readonly TypeAttributes DefaultTypeAttributes;
2420 static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
2421 MemberName name, int mod_flags, Kind kind,
2422 Location loc)
2424 PartialContainer pc;
2425 string full_name = name.GetName (true);
2426 DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [full_name];
2427 if (ds != null) {
2428 pc = ds as PartialContainer;
2430 if (pc == null) {
2431 Report.Error (
2432 260, ds.Location, "Missing partial modifier " +
2433 "on declaration of type `{0}'; another " +
2434 "partial implementation of this type exists",
2435 name);
2437 Report.LocationOfPreviousError (loc);
2438 return null;
2441 if (pc.Kind != kind) {
2442 Report.Error (
2443 261, loc, "Partial declarations of `{0}' " +
2444 "must be all classes, all structs or " +
2445 "all interfaces", name);
2446 return null;
2449 if (pc.OriginalModFlags != mod_flags) {
2450 Report.Error (
2451 262, loc, "Partial declarations of `{0}' " +
2452 "have conflicting accessibility modifiers",
2453 name);
2454 return null;
2457 return pc;
2460 pc = new PartialContainer (ns, parent, name, mod_flags, kind, loc);
2461 RootContext.Tree.RecordDecl (full_name, pc);
2462 parent.AddType (pc);
2463 pc.Register ();
2464 return pc;
2467 public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
2468 MemberName name, int mod, Attributes attrs,
2469 Kind kind, Location loc)
2471 PartialContainer pc = Create (ns, parent, name, mod, kind, loc);
2472 if (pc == null) {
2473 // An error occured; create a dummy container, but don't
2474 // register it.
2475 pc = new PartialContainer (ns, parent, name, mod, kind, loc);
2478 ClassPart part = new ClassPart (ns, pc, mod, attrs, kind, loc);
2479 pc.AddPart (part);
2480 return part;
2483 protected PartialContainer (NamespaceEntry ns, TypeContainer parent,
2484 MemberName name, int mod, Kind kind, Location l)
2485 : base (ns, parent, name, null, kind, l)
2487 this.Namespace = ns.NS;
2489 switch (kind) {
2490 case Kind.Class:
2491 AllowedModifiers = Class.AllowedModifiers;
2492 DefaultTypeAttributes = Class.DefaultTypeAttributes;
2493 break;
2495 case Kind.Struct:
2496 AllowedModifiers = Struct.AllowedModifiers;
2497 DefaultTypeAttributes = Struct.DefaultTypeAttributes;
2498 break;
2500 case Kind.Interface:
2501 AllowedModifiers = Interface.AllowedModifiers;
2502 DefaultTypeAttributes = Interface.DefaultTypeAttributes;
2503 break;
2505 default:
2506 throw new InvalidOperationException ();
2509 int accmods;
2510 if (parent.Parent == null)
2511 accmods = Modifiers.INTERNAL;
2512 else
2513 accmods = Modifiers.PRIVATE;
2515 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2516 this.OriginalModFlags = mod;
2519 public override void Register ()
2521 if (Kind == Kind.Interface)
2522 Parent.AddInterface (this);
2523 else if (Kind == Kind.Class || Kind == Kind.Struct)
2524 Parent.AddClassOrStruct (this);
2525 else
2526 throw new InvalidOperationException ();
2529 public override PendingImplementation GetPendingImplementations ()
2531 return PendingImplementation.GetPendingImplementations (this);
2534 public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
2535 Location l)
2537 ClassPart part = new ClassPart (ns, this, mod, attrs, Kind, l);
2538 AddPart (part);
2539 return part;
2542 public override TypeAttributes TypeAttr {
2543 get {
2544 return base.TypeAttr | DefaultTypeAttributes;
2549 public class ClassPart : TypeContainer, IMemberContainer {
2550 public readonly PartialContainer PartialContainer;
2551 public readonly bool IsPartial;
2553 public ClassPart (NamespaceEntry ns, PartialContainer parent,
2554 int mod, Attributes attrs, Kind kind, Location l)
2555 : base (ns, parent.Parent, parent.MemberName, attrs, kind, l)
2557 this.PartialContainer = parent;
2558 this.IsPartial = true;
2560 int accmods;
2561 if (parent.Parent == null)
2562 accmods = Modifiers.INTERNAL;
2563 else
2564 accmods = Modifiers.PRIVATE;
2566 this.ModFlags = Modifiers.Check (
2567 parent.AllowedModifiers, mod, accmods, l);
2570 public override void Register ()
2574 public override PendingImplementation GetPendingImplementations ()
2576 return PartialContainer.Pending;
2579 public override bool VerifyImplements (Type interface_type, string full,
2580 string name, Location loc)
2582 return PartialContainer.VerifyImplements (
2583 interface_type, full, name, loc);
2586 public override IMemberContainer ParentContainer {
2587 get {
2588 return PartialContainer.ParentContainer;
2593 public abstract class ClassOrStruct : TypeContainer {
2594 bool hasExplicitLayout = false;
2595 ListDictionary declarative_security;
2597 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
2598 MemberName name, Attributes attrs, Kind kind,
2599 Location l)
2600 : base (ns, parent, name, attrs, kind, l)
2604 public override PendingImplementation GetPendingImplementations ()
2606 return PendingImplementation.GetPendingImplementations (this);
2609 public override bool HasExplicitLayout {
2610 get {
2611 return hasExplicitLayout;
2615 protected override void VerifyMembers (EmitContext ec)
2617 base.VerifyMembers (ec);
2619 if ((events != null) && (RootContext.WarningLevel >= 3)) {
2620 foreach (Event e in events){
2621 if (e.status == 0)
2622 Report.Warning (67, e.Location, "The event '{0}' is never used", e.GetSignatureForError ());
2627 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2629 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2630 if (declarative_security == null)
2631 declarative_security = new ListDictionary ();
2633 a.ExtractSecurityPermissionSet (declarative_security);
2634 return;
2637 if (a.Type == TypeManager.struct_layout_attribute_type
2638 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2639 hasExplicitLayout = true;
2641 base.ApplyAttributeBuilder (a, cb);
2644 public override void Emit()
2646 base.Emit ();
2648 if (declarative_security != null) {
2649 foreach (DictionaryEntry de in declarative_security) {
2650 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2655 public override void Register ()
2657 Parent.AddClassOrStruct (this);
2661 /// <summary>
2662 /// Class handles static classes declaration
2663 /// </summary>
2664 public sealed class StaticClass: Class {
2665 public StaticClass (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
2666 Attributes attrs, Location l)
2667 : base (ns, parent, name, mod & ~Modifiers.STATIC, attrs, l)
2669 if (RootContext.Version == LanguageVersion.ISO_1) {
2670 Report.FeatureIsNotStandardized (l, "static classes");
2671 Environment.Exit (1);
2675 protected override void DefineContainerMembers (MemberCoreArrayList list)
2677 if (list == null)
2678 return;
2680 foreach (MemberCore m in list) {
2681 if (m is Operator) {
2682 Report.Error (715, m.Location, "'{0}': static classes cannot contain user-defined operators", m.GetSignatureForError (this));
2683 continue;
2686 if ((m.ModFlags & Modifiers.STATIC) != 0)
2687 continue;
2689 if (m is Constructor) {
2690 Report.Error (710, m.Location, "'{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2691 continue;
2694 if (m is Destructor) {
2695 Report.Error (711, m.Location, "'{0}': Static class cannot contain destructor", GetSignatureForError ());
2696 continue;
2699 Report.Error (708, m.Location, "'{0}': cannot declare instance members in a static class", m.GetSignatureForError (this));
2702 base.DefineContainerMembers (list);
2705 public override TypeBuilder DefineType()
2707 TypeBuilder tb = base.DefineType ();
2708 if (tb == null)
2709 return null;
2711 if (base_class_type != TypeManager.object_type) {
2712 Report.Error (713, Location, "Static class '{0}' cannot derive from type '{1}'. Static classes must derive from object", GetSignatureForError (), TypeManager.CSharpName (base_class_type));
2713 return null;
2716 if (base_inteface_types != null) {
2717 foreach (Type t in base_inteface_types)
2718 Report.SymbolRelatedToPreviousError (t);
2719 Report.Error (714, Location, "'{0}': static classes cannot implement interfaces", GetSignatureForError ());
2721 return tb;
2724 public override TypeAttributes TypeAttr {
2725 get {
2726 return base.TypeAttr | TypeAttributes.Abstract | TypeAttributes.Sealed;
2731 public class Class : ClassOrStruct {
2732 // <summary>
2733 // Modifiers allowed in a class declaration
2734 // </summary>
2735 public const int AllowedModifiers =
2736 Modifiers.NEW |
2737 Modifiers.PUBLIC |
2738 Modifiers.PROTECTED |
2739 Modifiers.INTERNAL |
2740 Modifiers.PRIVATE |
2741 Modifiers.ABSTRACT |
2742 Modifiers.SEALED |
2743 Modifiers.UNSAFE;
2745 // Information in the case we are an attribute type
2746 AttributeUsageAttribute attribute_usage;
2748 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
2749 Attributes attrs, Location l)
2750 : base (ns, parent, name, attrs, Kind.Class, l)
2752 int accmods;
2754 if (parent.Parent == null)
2755 accmods = Modifiers.INTERNAL;
2756 else
2757 accmods = Modifiers.PRIVATE;
2759 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2760 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.SEALED)) == (Modifiers.ABSTRACT | Modifiers.SEALED)) {
2761 Report.Error (502, Location, "'{0}' cannot be both abstract and sealed", GetSignatureForError ());
2764 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2767 public override AttributeTargets AttributeTargets {
2768 get {
2769 return AttributeTargets.Class;
2773 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2775 if (a.UsageAttribute != null) {
2776 if (base_class_type != TypeManager.attribute_type && !base_class_type.IsSubclassOf (TypeManager.attribute_type) &&
2777 TypeBuilder.FullName != "System.Attribute") {
2778 Report.Error (641, a.Location, "Attribute '{0}' is only valid on classes derived from System.Attribute", a.Name);
2780 attribute_usage = a.UsageAttribute;
2783 base.ApplyAttributeBuilder (a, cb);
2786 public AttributeUsageAttribute AttributeUsage {
2787 get {
2788 return attribute_usage;
2792 public const TypeAttributes DefaultTypeAttributes =
2793 TypeAttributes.AutoLayout | TypeAttributes.Class;
2796 // FIXME: How do we deal with the user specifying a different
2797 // layout?
2799 public override TypeAttributes TypeAttr {
2800 get {
2801 return base.TypeAttr | DefaultTypeAttributes;
2806 public class Struct : ClassOrStruct {
2807 // <summary>
2808 // Modifiers allowed in a struct declaration
2809 // </summary>
2810 public const int AllowedModifiers =
2811 Modifiers.NEW |
2812 Modifiers.PUBLIC |
2813 Modifiers.PROTECTED |
2814 Modifiers.INTERNAL |
2815 Modifiers.UNSAFE |
2816 Modifiers.PRIVATE;
2818 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2819 int mod, Attributes attrs, Location l)
2820 : base (ns, parent, name, attrs, Kind.Struct, l)
2822 int accmods;
2824 if (parent.Parent == null)
2825 accmods = Modifiers.INTERNAL;
2826 else
2827 accmods = Modifiers.PRIVATE;
2829 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2831 this.ModFlags |= Modifiers.SEALED;
2834 public override AttributeTargets AttributeTargets {
2835 get {
2836 return AttributeTargets.Struct;
2840 public const TypeAttributes DefaultTypeAttributes =
2841 TypeAttributes.SequentialLayout |
2842 TypeAttributes.Sealed |
2843 TypeAttributes.BeforeFieldInit;
2846 // FIXME: Allow the user to specify a different set of attributes
2847 // in some cases (Sealed for example is mandatory for a class,
2848 // but what SequentialLayout can be changed
2850 public override TypeAttributes TypeAttr {
2851 get {
2852 return base.TypeAttr | DefaultTypeAttributes;
2857 /// <summary>
2858 /// Interfaces
2859 /// </summary>
2860 public class Interface : TypeContainer, IMemberContainer {
2861 /// <summary>
2862 /// Modifiers allowed in a class declaration
2863 /// </summary>
2864 public const int AllowedModifiers =
2865 Modifiers.NEW |
2866 Modifiers.PUBLIC |
2867 Modifiers.PROTECTED |
2868 Modifiers.INTERNAL |
2869 Modifiers.UNSAFE |
2870 Modifiers.PRIVATE;
2872 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
2873 Attributes attrs, Location l)
2874 : base (ns, parent, name, attrs, Kind.Interface, l)
2876 int accmods;
2878 if (parent.Parent == null)
2879 accmods = Modifiers.INTERNAL;
2880 else
2881 accmods = Modifiers.PRIVATE;
2883 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2886 public override void Register ()
2888 Parent.AddInterface (this);
2891 public override PendingImplementation GetPendingImplementations ()
2893 return null;
2896 public override AttributeTargets AttributeTargets {
2897 get {
2898 return AttributeTargets.Interface;
2902 public const TypeAttributes DefaultTypeAttributes =
2903 TypeAttributes.AutoLayout |
2904 TypeAttributes.Abstract |
2905 TypeAttributes.Interface;
2907 public override TypeAttributes TypeAttr {
2908 get {
2909 return base.TypeAttr | DefaultTypeAttributes;
2914 public abstract class MethodCore : MemberBase {
2915 public readonly Parameters Parameters;
2916 protected ToplevelBlock block;
2919 // Parameters, cached for semantic analysis.
2921 protected InternalParameters parameter_info;
2922 protected Type [] parameter_types;
2924 // Whether this is an operator method.
2925 public bool IsOperator;
2928 // The method we're overriding if this is an override method.
2930 protected MethodInfo parent_method = null;
2932 static string[] attribute_targets = new string [] { "method", "return" };
2934 public MethodCore (TypeContainer parent, Expression type, int mod,
2935 int allowed_mod, bool is_interface, MemberName name,
2936 Attributes attrs, Parameters parameters, Location loc)
2937 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
2938 attrs, loc)
2940 Parameters = parameters;
2941 IsInterface = is_interface;
2945 // Returns the System.Type array for the parameters of this method
2947 public Type [] ParameterTypes {
2948 get {
2949 return parameter_types;
2953 public InternalParameters ParameterInfo
2955 get {
2956 return parameter_info;
2960 public ToplevelBlock Block {
2961 get {
2962 return block;
2965 set {
2966 block = value;
2970 protected override bool CheckBase ()
2972 if (!base.CheckBase ())
2973 return false;
2975 // Check whether arguments were correct.
2976 if (!DoDefineParameters ())
2977 return false;
2979 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
2980 return false;
2982 if (IsExplicitImpl)
2983 return true;
2985 // Is null for System.Object while compiling corlib and base interfaces
2986 if (Parent.ParentContainer == null) {
2987 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
2988 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
2990 return true;
2993 Type parent_ret_type = null;
2994 parent_method = FindOutParentMethod (Parent, ref parent_ret_type);
2996 // method is override
2997 if (parent_method != null) {
2999 if (!CheckMethodAgainstBase ())
3000 return false;
3002 if ((ModFlags & Modifiers.NEW) == 0) {
3003 if (MemberType != TypeManager.TypeToCoreType (parent_ret_type)) {
3004 Report.SymbolRelatedToPreviousError (parent_method);
3005 Report.Error (508, Location, GetSignatureForError (Parent) + ": cannot " +
3006 "change return type when overriding inherited member");
3007 return false;
3009 } else {
3010 if (parent_method.IsAbstract && !IsInterface) {
3011 Report.SymbolRelatedToPreviousError (parent_method);
3012 Report.Error (533, Location, "'{0}' hides inherited abstract member", GetSignatureForError (Parent));
3013 return false;
3017 if (parent_method.IsSpecialName && !(this is PropertyBase)) {
3018 Report.Error (561, Location, "'{0}': cannot override '{1}' because it is a special compiler-generated method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (parent_method));
3019 return false;
3022 if (RootContext.WarningLevel > 2) {
3023 if (Name == "Equals" && parameter_types.Length == 1 && parameter_types [0] == TypeManager.object_type)
3024 Parent.Methods.HasEquals = true;
3025 else if (Name == "GetHashCode" && parameter_types.Length == 0)
3026 Parent.Methods.HasGetHashCode = true;
3029 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
3030 if (oa != null) {
3031 EmitContext ec = new EmitContext (this.Parent, this.Parent, Location, null, null, ModFlags, false);
3032 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type, ec)) {
3033 Report.SymbolRelatedToPreviousError (parent_method);
3034 Report.Warning (672, 1, Location, "Member '{0}' overrides obsolete member. Add the Obsolete attribute to '{0}'", GetSignatureForError (Parent));
3037 return true;
3040 MemberInfo conflict_symbol = Parent.FindMemberWithSameName (Name, !(this is Property));
3041 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3042 if (conflict_symbol != null) {
3043 Report.SymbolRelatedToPreviousError (conflict_symbol);
3044 if (this is PropertyBase)
3045 Report.Error (544, Location, "'{0}': cannot override because '{1}' is not a property", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
3046 else
3047 Report.Error (505, Location, "'{0}': cannot override because '{1}' is not a method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
3048 } else
3049 Report.Error (115, Location, "'{0}': no suitable methods found to override", GetSignatureForError (Parent));
3050 return false;
3053 if (conflict_symbol == null) {
3054 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3055 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
3057 return true;
3060 if ((ModFlags & Modifiers.NEW) == 0) {
3061 if (this is Method && conflict_symbol is MethodBase)
3062 return true;
3064 Report.SymbolRelatedToPreviousError (conflict_symbol);
3065 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
3068 return true;
3073 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3074 // that have been defined.
3076 // `name' is the user visible name for reporting errors (this is used to
3077 // provide the right name regarding method names and properties)
3079 bool CheckMethodAgainstBase ()
3081 bool ok = true;
3083 // TODO: replace with GetSignatureForError
3084 string name = parent_method.DeclaringType.Name + "." + parent_method.Name;
3086 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3087 if (!(parent_method.IsAbstract || parent_method.IsVirtual)){
3088 Report.Error (
3089 506, Location, Parent.MakeName (Name) +
3090 ": cannot override inherited member `" +
3091 name + "' because it is not " +
3092 "virtual, abstract or override");
3093 ok = false;
3096 // Now we check that the overriden method is not final
3098 if (parent_method.IsFinal) {
3099 // This happens when implementing interface methods.
3100 if (parent_method.IsHideBySig && parent_method.IsVirtual) {
3101 Report.Error (
3102 506, Location, Parent.MakeName (Name) +
3103 ": cannot override inherited member `" +
3104 name + "' because it is not " +
3105 "virtual, abstract or override");
3106 } else
3107 Report.Error (239, Location, Parent.MakeName (Name) + " : cannot " +
3108 "override inherited member `" + name +
3109 "' because it is sealed.");
3110 ok = false;
3113 // Check that the permissions are not being changed
3115 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3116 MethodAttributes parentp = parent_method.Attributes & MethodAttributes.MemberAccessMask;
3119 // special case for "protected internal"
3122 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3124 // when overriding protected internal, the method can be declared
3125 // protected internal only within the same assembly
3128 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3129 if (Parent.TypeBuilder.Assembly != parent_method.DeclaringType.Assembly){
3131 // assemblies differ - report an error
3134 Error_CannotChangeAccessModifiers (Parent, parent_method, name);
3135 ok = false;
3136 } else if (thisp != parentp) {
3138 // same assembly, but other attributes differ - report an error
3141 Error_CannotChangeAccessModifiers (Parent, parent_method, name);
3142 ok = false;
3144 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3146 // if it's not "protected internal", it must be "protected"
3149 Error_CannotChangeAccessModifiers (Parent, parent_method, name);
3150 ok = false;
3151 } else if (Parent.TypeBuilder.Assembly == parent_method.DeclaringType.Assembly) {
3153 // protected within the same assembly - an error
3155 Error_CannotChangeAccessModifiers (Parent, parent_method, name);
3156 ok = false;
3157 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3158 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3160 // protected ok, but other attributes differ - report an error
3162 Error_CannotChangeAccessModifiers (Parent, parent_method, name);
3163 ok = false;
3165 } else {
3166 if (thisp != parentp){
3167 Error_CannotChangeAccessModifiers (Parent, parent_method, name);
3168 ok = false;
3173 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
3174 ModFlags |= Modifiers.NEW;
3175 Report.SymbolRelatedToPreviousError (parent_method);
3176 if (!IsInterface && (parent_method.IsVirtual || parent_method.IsAbstract)) {
3177 if (RootContext.WarningLevel >= 2)
3178 Report.Warning (114, Location, "'{0}' hides inherited member '{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", GetSignatureForError (Parent), TypeManager.CSharpSignature (parent_method));
3179 } else
3180 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
3183 return ok;
3186 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method, string name)
3189 // FIXME: report the old/new permissions?
3191 Report.Error (
3192 507, Location, parent.MakeName (Name) +
3193 ": can't change the access modifiers when overriding inherited " +
3194 "member `" + name + "'");
3197 protected static string Error722 {
3198 get {
3199 return "'{0}': static types cannot be used as return types";
3203 /// <summary>
3204 /// For custom member duplication search in a container
3205 /// </summary>
3206 protected abstract bool CheckForDuplications ();
3208 /// <summary>
3209 /// Gets parent method and its return type
3210 /// </summary>
3211 protected abstract MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type);
3213 protected virtual bool DoDefineParameters ()
3215 EmitContext ec = Parent.EmitContext;
3216 if (ec == null)
3217 throw new InternalErrorException ("DoDefineParameters invoked too early");
3219 bool old_unsafe = ec.InUnsafe;
3220 ec.InUnsafe = InUnsafe;
3221 // Check if arguments were correct
3222 parameter_types = Parameters.GetParameterInfo (ec);
3223 ec.InUnsafe = old_unsafe;
3225 if ((parameter_types == null) ||
3226 !CheckParameters (Parent, parameter_types))
3227 return false;
3229 parameter_info = new InternalParameters (parameter_types, Parameters);
3231 Parameter array_param = Parameters.ArrayParameter;
3232 if ((array_param != null) &&
3233 (!array_param.ParameterType.IsArray ||
3234 (array_param.ParameterType.GetArrayRank () != 1))) {
3235 Report.Error (225, Location, "params parameter has to be a single dimensional array");
3236 return false;
3239 return true;
3242 public override string[] ValidAttributeTargets {
3243 get {
3244 return attribute_targets;
3248 protected override bool VerifyClsCompliance (DeclSpace ds)
3250 if (!base.VerifyClsCompliance (ds)) {
3251 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
3252 Report.Error (3011, Location, "'{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3254 return false;
3257 if (Parameters.HasArglist) {
3258 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3261 if (!AttributeTester.IsClsCompliant (MemberType)) {
3262 Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant", GetSignatureForError ());
3265 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
3267 return true;
3270 protected bool IsDuplicateImplementation (MethodCore method)
3272 if ((method == this) || (method.Name != Name))
3273 return false;
3275 Type[] param_types = method.ParameterTypes;
3276 if (param_types == null)
3277 return false;
3279 if (param_types.Length != ParameterTypes.Length)
3280 return false;
3282 for (int i = 0; i < param_types.Length; i++)
3283 if (param_types [i] != ParameterTypes [i])
3284 return false;
3286 // TODO: make operator compatible with MethodCore to avoid this
3287 if (this is Operator && method is Operator) {
3288 if (MemberType != method.MemberType)
3289 return false;
3293 // Try to report 663: method only differs on out/ref
3295 ParameterData info = ParameterInfo;
3296 ParameterData other_info = method.ParameterInfo;
3297 for (int i = 0; i < info.Count; i++){
3298 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3299 Report.Error (663, Location, "Overload method only differs in parameter modifier");
3300 return false;
3304 Report.SymbolRelatedToPreviousError (method);
3305 Report.Error (111, Location, TypeContainer.Error111, Parent.Name, Name);
3306 return true;
3309 protected override void VerifyObsoleteAttribute()
3311 base.VerifyObsoleteAttribute ();
3313 if (parameter_types == null)
3314 return;
3316 foreach (Type type in parameter_types) {
3317 CheckUsageOfObsoleteAttribute (type);
3322 public class SourceMethod : ISourceMethod
3324 TypeContainer container;
3325 MethodBase builder;
3327 protected SourceMethod (TypeContainer container, MethodBase builder,
3328 ISourceFile file, Location start, Location end)
3330 this.container = container;
3331 this.builder = builder;
3333 CodeGen.SymbolWriter.OpenMethod (
3334 file, this, start.Row, 0, end.Row, 0);
3337 public string Name {
3338 get { return builder.Name; }
3341 public int NamespaceID {
3342 get { return container.NamespaceEntry.SymbolFileID; }
3345 public int Token {
3346 get {
3347 if (builder is MethodBuilder)
3348 return ((MethodBuilder) builder).GetToken ().Token;
3349 else if (builder is ConstructorBuilder)
3350 return ((ConstructorBuilder) builder).GetToken ().Token;
3351 else
3352 throw new NotSupportedException ();
3356 public void CloseMethod ()
3358 if (CodeGen.SymbolWriter != null)
3359 CodeGen.SymbolWriter.CloseMethod ();
3362 public static SourceMethod Create (TypeContainer parent,
3363 MethodBase builder, Block block)
3365 if (CodeGen.SymbolWriter == null)
3366 return null;
3367 if (block == null)
3368 return null;
3370 Location start_loc = block.StartLocation;
3371 if (Location.IsNull (start_loc))
3372 return null;
3374 Location end_loc = block.EndLocation;
3375 if (Location.IsNull (end_loc))
3376 return null;
3378 ISourceFile file = start_loc.SourceFile;
3379 if (file == null)
3380 return null;
3382 return new SourceMethod (
3383 parent, builder, file, start_loc, end_loc);
3387 public class Method : MethodCore, IIteratorContainer, IMethodData {
3388 public MethodBuilder MethodBuilder;
3389 public MethodData MethodData;
3390 ReturnParameter return_attributes;
3391 ListDictionary declarative_security;
3393 /// <summary>
3394 /// Modifiers allowed in a class declaration
3395 /// </summary>
3396 const int AllowedModifiers =
3397 Modifiers.NEW |
3398 Modifiers.PUBLIC |
3399 Modifiers.PROTECTED |
3400 Modifiers.INTERNAL |
3401 Modifiers.PRIVATE |
3402 Modifiers.STATIC |
3403 Modifiers.VIRTUAL |
3404 Modifiers.SEALED |
3405 Modifiers.OVERRIDE |
3406 Modifiers.ABSTRACT |
3407 Modifiers.UNSAFE |
3408 Modifiers.METHOD_YIELDS |
3409 Modifiers.EXTERN;
3411 const int AllowedInterfaceModifiers =
3412 Modifiers.NEW | Modifiers.UNSAFE;
3415 // return_type can be "null" for VOID values.
3417 public Method (TypeContainer ds, Expression return_type, int mod, bool is_iface,
3418 MemberName name, Parameters parameters, Attributes attrs,
3419 Location l)
3420 : base (ds, return_type, mod,
3421 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3422 is_iface, name, attrs, parameters, l)
3426 public override AttributeTargets AttributeTargets {
3427 get {
3428 return AttributeTargets.Method;
3432 public override string GetSignatureForError()
3434 if (MethodBuilder == null) {
3435 return GetSignatureForError (Parent);
3437 return TypeManager.CSharpSignature (MethodBuilder);
3440 /// <summary>
3441 /// Use this method when MethodBuilder is null
3442 /// </summary>
3443 public override string GetSignatureForError (TypeContainer tc)
3445 // TODO: get params from somewhere
3446 if (parameter_info == null)
3447 return base.GetSignatureForError (tc);
3449 // TODO: move to parameters
3450 System.Text.StringBuilder args = new System.Text.StringBuilder ();
3451 if (parameter_info.Parameters.FixedParameters != null) {
3452 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
3453 Parameter p = parameter_info.Parameters.FixedParameters [i];
3454 args.Append (p.GetSignatureForError ());
3456 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
3457 args.Append (',');
3461 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
3464 void DuplicateEntryPoint (MethodInfo b, Location location)
3466 Report.Error (
3467 17, location,
3468 "Program `" + CodeGen.FileName +
3469 "' has more than one entry point defined: `" +
3470 TypeManager.CSharpSignature(b) + "'");
3473 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
3475 if (b.ReturnType != TypeManager.void_type &&
3476 b.ReturnType != TypeManager.int32_type)
3477 return false;
3479 if (pinfo.Count == 0)
3480 return true;
3482 if (pinfo.Count > 1)
3483 return false;
3485 Type t = pinfo.ParameterType(0);
3486 if (t.IsArray &&
3487 (t.GetArrayRank() == 1) &&
3488 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3489 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3490 return true;
3491 else
3492 return false;
3495 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3497 if (a.Target == AttributeTargets.ReturnValue) {
3498 if (return_attributes == null)
3499 return_attributes = new ReturnParameter (MethodBuilder, Location);
3501 return_attributes.ApplyAttributeBuilder (a, cb);
3502 return;
3505 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
3506 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3509 if (a.Type == TypeManager.dllimport_type) {
3510 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3511 if ((ModFlags & extern_static) != extern_static) {
3512 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3515 return;
3518 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
3519 if (declarative_security == null)
3520 declarative_security = new ListDictionary ();
3521 a.ExtractSecurityPermissionSet (declarative_security);
3522 return;
3525 if (a.Type == TypeManager.conditional_attribute_type) {
3526 if (IsOperator || IsExplicitImpl) {
3527 Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
3528 return;
3531 if (ReturnType != TypeManager.void_type) {
3532 Report.Error (578, Location, "Conditional not valid on '{0}' because its return new ErrorData ( type is not void", GetSignatureForError ());
3533 return;
3536 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3537 Report.Error (243, Location, "Conditional not valid on '{0}' because it is an override method", GetSignatureForError ());
3538 return;
3541 if (IsInterface) {
3542 Report.Error (582, Location, "Conditional not valid on interface members");
3543 return;
3546 if (MethodData.IsImplementing) {
3547 Report.Error (629, Location, "Conditional member '{0}' cannot implement interface member", GetSignatureForError ());
3548 return;
3551 for (int i = 0; i < parameter_info.Count; ++i) {
3552 if ((parameter_info.ParameterModifier (i) & Parameter.Modifier.OUT) != 0) {
3553 Report.Error (685, Location, "Conditional method '{0}' cannot have an out parameter", GetSignatureForError ());
3554 return;
3559 MethodBuilder.SetCustomAttribute (cb);
3562 protected override bool CheckForDuplications ()
3564 ArrayList ar = Parent.Methods;
3565 if (ar != null) {
3566 int arLen = ar.Count;
3568 for (int i = 0; i < arLen; i++) {
3569 Method m = (Method) ar [i];
3570 if (IsDuplicateImplementation (m))
3571 return false;
3575 ar = Parent.Properties;
3576 if (ar != null) {
3577 for (int i = 0; i < ar.Count; ++i) {
3578 PropertyBase pb = (PropertyBase) ar [i];
3579 if (pb.AreAccessorsDuplicateImplementation (this))
3580 return false;
3584 ar = Parent.Indexers;
3585 if (ar != null) {
3586 for (int i = 0; i < ar.Count; ++i) {
3587 PropertyBase pb = (PropertyBase) ar [i];
3588 if (pb.AreAccessorsDuplicateImplementation (this))
3589 return false;
3593 ar = Parent.Events;
3594 if (ar != null) {
3595 for (int i = 0; i < ar.Count; ++i) {
3596 Event ev = (Event) ar [i];
3597 if (ev.AreAccessorsDuplicateImplementation (this))
3598 return false;
3602 return true;
3606 // Creates the type
3608 public override bool Define ()
3610 if (!DoDefine ())
3611 return false;
3613 if (!CheckBase ())
3614 return false;
3616 if (IsOperator)
3617 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3619 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags, this);
3621 if (!MethodData.Define (Parent))
3622 return false;
3625 // Setup iterator if we are one
3627 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3628 Iterator iterator = new Iterator (
3629 Parent, Name, MemberType, ParameterTypes,
3630 ParameterInfo, ModFlags, block, Location);
3632 if (!iterator.DefineIterator ())
3633 return false;
3635 block = iterator.Block;
3638 MethodBuilder = MethodData.MethodBuilder;
3641 // This is used to track the Entry Point,
3643 if (Name == "Main" &&
3644 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3645 (RootContext.MainClass == null ||
3646 RootContext.MainClass == Parent.TypeBuilder.FullName)){
3647 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3648 if (RootContext.EntryPoint == null) {
3649 RootContext.EntryPoint = MethodBuilder;
3650 RootContext.EntryPointLocation = Location;
3651 } else {
3652 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3653 DuplicateEntryPoint (MethodBuilder, Location);
3655 } else {
3656 if (RootContext.WarningLevel >= 4)
3657 Report.Warning (28, Location, "'{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder));
3661 if (MemberType.IsAbstract && MemberType.IsSealed) {
3662 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3663 return false;
3666 return true;
3670 // Emits the code
3672 public override void Emit ()
3674 MethodData.Emit (Parent, this);
3675 base.Emit ();
3677 if (declarative_security != null) {
3678 foreach (DictionaryEntry de in declarative_security) {
3679 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3683 Block = null;
3684 MethodData = null;
3687 protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
3689 MethodInfo mi = (MethodInfo) container.ParentContainer.MemberCache.FindMemberToOverride (
3690 container.TypeBuilder, Name, ParameterTypes, false);
3692 if (mi == null)
3693 return null;
3695 parent_ret_type = mi.ReturnType;
3696 return mi;
3699 protected override bool VerifyClsCompliance(DeclSpace ds)
3701 if (!base.VerifyClsCompliance (ds))
3702 return false;
3704 if (parameter_types.Length > 0) {
3705 ArrayList al = (ArrayList)ds.MemberCache.Members [Name];
3706 if (al.Count > 1)
3707 ds.MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
3710 return true;
3714 void IIteratorContainer.SetYields ()
3716 ModFlags |= Modifiers.METHOD_YIELDS;
3719 #region IMethodData Members
3721 public CallingConventions CallingConventions {
3722 get {
3723 CallingConventions cc = Parameters.GetCallingConvention ();
3724 if (Parameters.HasArglist)
3725 block.HasVarargs = true;
3727 if (!IsInterface)
3728 if ((ModFlags & Modifiers.STATIC) == 0)
3729 cc |= CallingConventions.HasThis;
3731 // FIXME: How is `ExplicitThis' used in C#?
3733 return cc;
3737 public Type ReturnType {
3738 get {
3739 return MemberType;
3743 public MemberName MethodName {
3744 get {
3745 return MemberName;
3749 public new Location Location {
3750 get {
3751 return base.Location;
3755 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3757 return new EmitContext (
3758 tc, Parent, Location, ig, ReturnType, ModFlags, false);
3761 public ObsoleteAttribute GetObsoleteAttribute ()
3763 return GetObsoleteAttribute (Parent);
3766 /// <summary>
3767 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3768 /// </summary>
3769 public bool IsExcluded (EmitContext ec)
3771 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3772 return (caching_flags & Flags.Excluded) != 0;
3774 caching_flags &= ~Flags.Excluded_Undetected;
3776 if (parent_method == null) {
3777 if (OptAttributes == null)
3778 return false;
3780 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3782 if (attrs == null)
3783 return false;
3785 foreach (Attribute a in attrs) {
3786 string condition = a.GetConditionalAttributeValue (
3787 Parent);
3788 if (RootContext.AllDefines.Contains (condition))
3789 return false;
3792 caching_flags |= Flags.Excluded;
3793 return true;
3796 IMethodData md = TypeManager.GetMethod (parent_method);
3797 if (md == null) {
3798 if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
3799 caching_flags |= Flags.Excluded;
3800 return true;
3802 return false;
3805 if (md.IsExcluded (ec)) {
3806 caching_flags |= Flags.Excluded;
3807 return true;
3809 return false;
3812 #endregion
3815 public abstract class ConstructorInitializer {
3816 ArrayList argument_list;
3817 protected ConstructorInfo parent_constructor;
3818 Parameters parameters;
3819 Location loc;
3821 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3822 Location loc)
3824 this.argument_list = argument_list;
3825 this.parameters = parameters;
3826 this.loc = loc;
3829 public ArrayList Arguments {
3830 get {
3831 return argument_list;
3835 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3837 Expression parent_constructor_group;
3838 Type t;
3840 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3842 if (argument_list != null){
3843 foreach (Argument a in argument_list){
3844 if (!a.Resolve (ec, loc))
3845 return false;
3848 ec.CurrentBlock = null;
3850 if (this is ConstructorBaseInitializer) {
3851 if (ec.ContainerType.BaseType == null)
3852 return true;
3854 t = ec.ContainerType.BaseType;
3855 if (ec.ContainerType.IsValueType) {
3856 Report.Error (522, loc,
3857 "structs cannot call base class constructors");
3858 return false;
3860 } else
3861 t = ec.ContainerType;
3863 parent_constructor_group = Expression.MemberLookup (
3864 ec, t, ".ctor", MemberTypes.Constructor,
3865 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3866 loc);
3868 if (parent_constructor_group == null){
3869 parent_constructor_group = Expression.MemberLookup (
3870 ec, t, ".ctor", MemberTypes.Constructor,
3871 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3872 loc);
3874 if (parent_constructor_group != null)
3875 Report.Error (
3876 112, loc, "`{0}.{1}' is inaccessible due to " +
3877 "its protection level", t.FullName, t.Name);
3878 else
3879 Report.Error (
3880 1501, loc, "Can not find a constructor for " +
3881 "this argument list");
3882 return false;
3885 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3886 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3887 false, loc);
3889 if (parent_constructor == null){
3890 Report.Error (1501, loc,
3891 "Can not find a constructor for this argument list");
3892 return false;
3895 if (parent_constructor == caller_builder){
3896 Report.Error (516, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3897 return false;
3900 return true;
3903 public void Emit (EmitContext ec)
3905 if (parent_constructor != null){
3906 ec.Mark (loc, false);
3907 if (ec.IsStatic)
3908 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3909 else
3910 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3914 /// <summary>
3915 /// Method search for base ctor. (We do not cache it).
3916 /// </summary>
3917 Constructor GetOverloadedConstructor (TypeContainer tc)
3919 if (tc.InstanceConstructors == null)
3920 return null;
3922 foreach (Constructor c in tc.InstanceConstructors) {
3923 if (Arguments == null) {
3924 if (c.ParameterTypes.Length == 0)
3925 return c;
3927 continue;
3930 bool ok = true;
3932 int count = c.ParameterInfo.Count;
3933 if ((count > 0) &&
3934 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
3935 for (int i = 0; i < count-1; i++)
3936 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3937 ok = false;
3938 break;
3940 } else {
3941 if (c.ParameterTypes.Length != Arguments.Count)
3942 continue;
3944 for (int i = 0; i < Arguments.Count; ++i)
3945 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3946 ok = false;
3947 break;
3951 if (!ok)
3952 continue;
3954 return c;
3957 return null;
3960 //TODO: implement caching when it will be necessary
3961 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
3963 Constructor ctor = GetOverloadedConstructor (tc);
3964 if (ctor == null)
3965 return;
3967 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
3968 if (oa == null)
3969 return;
3971 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
3975 public class ConstructorBaseInitializer : ConstructorInitializer {
3976 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3977 base (argument_list, pars, l)
3981 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
3982 if (parent_constructor == null)
3983 return;
3985 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.base_class_type);
3986 if (type_ds == null) {
3987 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
3989 if (oa != null)
3990 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
3992 return;
3995 base.CheckObsoleteAttribute (type_ds, loc);
4000 public class ConstructorThisInitializer : ConstructorInitializer {
4001 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
4002 base (argument_list, pars, l)
4007 public class Constructor : MethodCore, IMethodData {
4008 public ConstructorBuilder ConstructorBuilder;
4009 public ConstructorInitializer Initializer;
4010 ListDictionary declarative_security;
4012 // <summary>
4013 // Modifiers allowed for a constructor.
4014 // </summary>
4015 public const int AllowedModifiers =
4016 Modifiers.PUBLIC |
4017 Modifiers.PROTECTED |
4018 Modifiers.INTERNAL |
4019 Modifiers.STATIC |
4020 Modifiers.UNSAFE |
4021 Modifiers.EXTERN |
4022 Modifiers.PRIVATE;
4024 bool has_compliant_args = false;
4026 // The spec claims that static is not permitted, but
4027 // my very own code has static constructors.
4029 public Constructor (TypeContainer ds, string name, int mod, Parameters args,
4030 ConstructorInitializer init, Location l)
4031 : base (ds, null, mod, AllowedModifiers, false, new MemberName (name),
4032 null, args, l)
4034 Initializer = init;
4037 public override string GetSignatureForError()
4039 if (ConstructorBuilder == null)
4040 return GetSignatureForError (Parent);
4042 return TypeManager.CSharpSignature (ConstructorBuilder);
4045 public bool HasCompliantArgs {
4046 get {
4047 return has_compliant_args;
4051 public override AttributeTargets AttributeTargets {
4052 get {
4053 return AttributeTargets.Constructor;
4059 // Returns true if this is a default constructor
4061 public bool IsDefault ()
4063 if ((ModFlags & Modifiers.STATIC) != 0)
4064 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4065 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
4067 else
4068 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4069 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
4070 (Initializer is ConstructorBaseInitializer) &&
4071 (Initializer.Arguments == null);
4074 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4076 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4077 if (declarative_security == null) {
4078 declarative_security = new ListDictionary ();
4080 a.ExtractSecurityPermissionSet (declarative_security);
4081 return;
4084 ConstructorBuilder.SetCustomAttribute (cb);
4087 protected override bool CheckForDuplications ()
4089 ArrayList ar = Parent.InstanceConstructors;
4090 if (ar != null) {
4091 int arLen = ar.Count;
4093 for (int i = 0; i < arLen; i++) {
4094 Constructor m = (Constructor) ar [i];
4095 if (IsDuplicateImplementation (m))
4096 return false;
4099 return true;
4102 protected override bool CheckBase ()
4104 // Check whether arguments were correct.
4105 if (!DoDefineParameters ())
4106 return false;
4108 // TODO: skip the rest for generated ctor
4109 if ((ModFlags & Modifiers.STATIC) != 0)
4110 return true;
4112 if (!CheckForDuplications ())
4113 return false;
4115 if (Parent.Kind == Kind.Struct) {
4116 if (ParameterTypes.Length == 0) {
4117 Report.Error (568, Location,
4118 "Structs can not contain explicit parameterless " +
4119 "constructors");
4120 return false;
4123 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4124 Report.Error (666, Location, "Protected member in struct declaration");
4125 return false;
4129 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4130 Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
4133 return true;
4137 // Creates the ConstructorBuilder
4139 public override bool Define ()
4141 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4142 MethodAttributes.SpecialName);
4144 if ((ModFlags & Modifiers.STATIC) != 0) {
4145 ca |= MethodAttributes.Static | MethodAttributes.Private;
4146 } else {
4147 ca |= MethodAttributes.HideBySig;
4149 if ((ModFlags & Modifiers.PUBLIC) != 0)
4150 ca |= MethodAttributes.Public;
4151 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4152 if ((ModFlags & Modifiers.INTERNAL) != 0)
4153 ca |= MethodAttributes.FamORAssem;
4154 else
4155 ca |= MethodAttributes.Family;
4156 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4157 ca |= MethodAttributes.Assembly;
4158 else if (IsDefault ())
4159 ca |= MethodAttributes.Public;
4160 else
4161 ca |= MethodAttributes.Private;
4164 // Check if arguments were correct.
4165 if (!CheckBase ())
4166 return false;
4168 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4169 ca, CallingConventions,
4170 ParameterTypes);
4172 if ((ModFlags & Modifiers.UNSAFE) != 0)
4173 ConstructorBuilder.InitLocals = false;
4175 TypeManager.AddMethod (ConstructorBuilder, this);
4178 // HACK because System.Reflection.Emit is lame
4180 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
4182 return true;
4186 // Emits the code
4188 public override void Emit ()
4190 EmitContext ec = CreateEmitContext (null, null);
4193 // extern methods have no bodies
4195 if ((ModFlags & Modifiers.EXTERN) != 0) {
4196 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
4197 Report.Error (
4198 179, Location, "External constructor `" +
4199 TypeManager.CSharpSignature (ConstructorBuilder) +
4200 "' can not have a body");
4201 return;
4203 } else if (block == null) {
4204 Report.Error (
4205 501, Location, "Constructor `" +
4206 TypeManager.CSharpSignature (ConstructorBuilder) +
4207 "' must declare a body since it is not marked extern");
4208 return;
4211 if ((ModFlags & Modifiers.STATIC) == 0){
4212 if (Parent.Kind == Kind.Class && Initializer == null)
4213 Initializer = new ConstructorBaseInitializer (
4214 null, Parameters.EmptyReadOnlyParameters, Location);
4218 // Spec mandates that Initializers will not have
4219 // `this' access
4221 ec.IsStatic = true;
4222 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
4223 return;
4224 ec.IsStatic = false;
4227 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
4229 SourceMethod source = SourceMethod.Create (
4230 Parent, ConstructorBuilder, block);
4233 // Classes can have base initializers and instance field initializers.
4235 if (Parent.Kind == Kind.Class){
4236 if ((ModFlags & Modifiers.STATIC) == 0){
4239 // If we use a "this (...)" constructor initializer, then
4240 // do not emit field initializers, they are initialized in the other constructor
4242 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4243 Parent.EmitFieldInitializers (ec);
4246 if (Initializer != null) {
4247 if (GetObsoleteAttribute (Parent) == null && Parent.GetObsoleteAttribute (Parent.Parent) == null)
4248 Initializer.CheckObsoleteAttribute (Parent, Location);
4249 else
4250 ec.TestObsoleteMethodUsage = false;
4251 Initializer.Emit (ec);
4254 if ((ModFlags & Modifiers.STATIC) != 0)
4255 Parent.EmitFieldInitializers (ec);
4257 if (OptAttributes != null)
4258 OptAttributes.Emit (ec, this);
4260 // If this is a non-static `struct' constructor and doesn't have any
4261 // initializer, it must initialize all of the struct's fields.
4262 if ((Parent.Kind == Kind.Struct) &&
4263 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4264 Block.AddThisVariable (Parent, Location);
4266 ec.EmitTopBlock (block, ParameterInfo, Location);
4268 if (source != null)
4269 source.CloseMethod ();
4271 base.Emit ();
4273 if (declarative_security != null) {
4274 foreach (DictionaryEntry de in declarative_security) {
4275 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4279 block = null;
4282 // Is never override
4283 protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
4285 return null;
4288 protected override bool VerifyClsCompliance (DeclSpace ds)
4290 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
4291 return false;
4294 if (parameter_types.Length > 0) {
4295 ArrayList al = (ArrayList)ds.MemberCache.Members [".ctor"];
4296 if (al.Count > 3)
4297 ds.MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4299 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4300 foreach (Type param in parameter_types) {
4301 if (param.IsArray) {
4302 return true;
4307 has_compliant_args = true;
4308 return true;
4311 #region IMethodData Members
4313 public System.Reflection.CallingConventions CallingConventions {
4314 get {
4315 CallingConventions cc = Parameters.GetCallingConvention ();
4317 if (Parent.Kind == Kind.Class)
4318 if ((ModFlags & Modifiers.STATIC) == 0)
4319 cc |= CallingConventions.HasThis;
4321 // FIXME: How is `ExplicitThis' used in C#?
4323 return cc;
4327 public new Location Location {
4328 get {
4329 return base.Location;
4333 public MemberName MethodName {
4334 get {
4335 return MemberName;
4339 public Type ReturnType {
4340 get {
4341 return MemberType;
4345 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4347 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4348 return new EmitContext (Parent, Location, ig_, null, ModFlags, true);
4351 public ObsoleteAttribute GetObsoleteAttribute ()
4353 return null;
4356 public bool IsExcluded(EmitContext ec)
4358 return false;
4361 #endregion
4364 /// <summary>
4365 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4366 /// </summary>
4367 public interface IMethodData
4369 CallingConventions CallingConventions { get; }
4370 Location Location { get; }
4371 MemberName MethodName { get; }
4372 Type[] ParameterTypes { get; }
4373 Type ReturnType { get; }
4375 Attributes OptAttributes { get; }
4376 ToplevelBlock Block { get; }
4378 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
4379 ObsoleteAttribute GetObsoleteAttribute ();
4380 string GetSignatureForError (TypeContainer tc);
4381 bool IsExcluded (EmitContext ec);
4382 bool IsClsCompliaceRequired (DeclSpace ds);
4386 // Encapsulates most of the Method's state
4388 public class MethodData {
4390 readonly IMethodData method;
4393 // The return type of this method
4395 public readonly InternalParameters ParameterInfo;
4398 // Are we implementing an interface ?
4400 public bool IsImplementing = false;
4403 // Protected data.
4405 protected MemberBase member;
4406 protected int modifiers;
4407 protected MethodAttributes flags;
4409 MethodBuilder builder = null;
4410 public MethodBuilder MethodBuilder {
4411 get {
4412 return builder;
4416 public MethodData (MemberBase member, InternalParameters parameters,
4417 int modifiers, MethodAttributes flags, IMethodData method)
4419 this.member = member;
4420 this.ParameterInfo = parameters;
4421 this.modifiers = modifiers;
4422 this.flags = flags;
4424 this.method = method;
4427 public bool Define (TypeContainer container)
4429 MethodInfo implementing = null;
4431 string name = method.MethodName.Name;
4432 string method_name = name;
4434 Type[] ParameterTypes = method.ParameterTypes;
4436 if (container.Pending != null){
4437 if (member is Indexer)
4438 implementing = container.Pending.IsInterfaceIndexer (
4439 member.InterfaceType, method.ReturnType, ParameterTypes);
4440 else
4441 implementing = container.Pending.IsInterfaceMethod (
4442 member.InterfaceType, name, method.ReturnType, ParameterTypes);
4444 if (member.InterfaceType != null){
4445 if (implementing == null){
4446 Report.Error (539, method.Location,
4447 "'{0}' in explicit interface declaration is not an interface", method_name);
4448 return false;
4450 method_name = member.InterfaceType.FullName + "." + name;
4455 // For implicit implementations, make sure we are public, for
4456 // explicit implementations, make sure we are private.
4458 if (implementing != null){
4460 // Setting null inside this block will trigger a more
4461 // verbose error reporting for missing interface implementations
4463 // The "candidate" function has been flagged already
4464 // but it wont get cleared
4466 if (member.IsExplicitImpl){
4467 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4468 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4469 implementing = null;
4471 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4472 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4474 // If this is an interface method implementation,
4475 // check for public accessibility
4477 implementing = null;
4478 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4479 // We may never be private.
4480 implementing = null;
4481 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4483 // We may be protected if we're overriding something.
4485 implementing = null;
4490 // Static is not allowed
4492 if ((modifiers & Modifiers.STATIC) != 0){
4493 implementing = null;
4494 Modifiers.Error_InvalidModifier (method.Location, "static");
4499 // If implementing is still valid, set flags
4501 if (implementing != null){
4503 // When implementing interface methods, set NewSlot
4504 // unless, we are overwriting a method.
4506 if (implementing.DeclaringType.IsInterface){
4507 if ((modifiers & Modifiers.OVERRIDE) == 0)
4508 flags |= MethodAttributes.NewSlot;
4510 flags |=
4511 MethodAttributes.Virtual |
4512 MethodAttributes.HideBySig;
4514 // Set Final unless we're virtual, abstract or already overriding a method.
4515 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4516 flags |= MethodAttributes.Final;
4518 IsImplementing = true;
4521 EmitContext ec = method.CreateEmitContext (container, null);
4523 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
4525 if (builder == null)
4526 return false;
4528 if ((modifiers & Modifiers.UNSAFE) != 0)
4529 builder.InitLocals = false;
4531 if (IsImplementing){
4533 // clear the pending implemntation flag
4535 if (member is Indexer) {
4536 container.Pending.ImplementIndexer (
4537 member.InterfaceType, builder, method.ReturnType,
4538 ParameterTypes, member.IsExplicitImpl);
4539 } else
4540 container.Pending.ImplementMethod (
4541 member.InterfaceType, name, method.ReturnType,
4542 ParameterTypes, member.IsExplicitImpl);
4544 if (member.IsExplicitImpl)
4545 container.TypeBuilder.DefineMethodOverride (
4546 builder, implementing);
4550 TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes);
4551 TypeManager.AddMethod (builder, method);
4553 return true;
4557 /// <summary>
4558 /// Create the MethodBuilder for the method
4559 /// </summary>
4560 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
4562 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4564 if ((modifiers & extern_static) == extern_static) {
4566 if (method.OptAttributes != null) {
4567 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
4568 if (dllimport_attribute != null) {
4569 flags |= MethodAttributes.PinvokeImpl;
4570 builder = dllimport_attribute.DefinePInvokeMethod (
4571 ec, container.TypeBuilder, method_name, flags,
4572 method.ReturnType, ParameterTypes);
4574 return;
4578 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4579 // We are more strict than Microsoft and report CS0626 like error
4580 if (method.OptAttributes == null ||
4581 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
4582 Report.Error (626, method.Location, "Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation", method.GetSignatureForError (container));
4583 return;
4587 builder = container.TypeBuilder.DefineMethod (
4588 method_name, flags, method.CallingConventions,
4589 method.ReturnType, ParameterTypes);
4593 // Emits the code
4595 public void Emit (TypeContainer container, Attributable kind)
4597 EmitContext ec;
4598 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4599 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
4600 else
4601 ec = method.CreateEmitContext (container, null);
4603 if (method.GetObsoleteAttribute () != null || container.GetObsoleteAttribute (container.Parent) != null)
4604 ec.TestObsoleteMethodUsage = false;
4606 Location loc = method.Location;
4607 Attributes OptAttributes = method.OptAttributes;
4609 if (OptAttributes != null)
4610 OptAttributes.Emit (ec, kind);
4612 if (member is MethodCore)
4613 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
4615 SymbolWriter sw = CodeGen.SymbolWriter;
4616 ToplevelBlock block = method.Block;
4619 // abstract or extern methods have no bodies
4621 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
4622 if (block == null)
4623 return;
4626 // abstract or extern methods have no bodies.
4628 if ((modifiers & Modifiers.ABSTRACT) != 0)
4629 Report.Error (
4630 500, method.Location, "Abstract method `" +
4631 TypeManager.CSharpSignature (builder) +
4632 "' can not have a body");
4634 if ((modifiers & Modifiers.EXTERN) != 0)
4635 Report.Error (
4636 179, method.Location, "External method `" +
4637 TypeManager.CSharpSignature (builder) +
4638 "' can not have a body");
4640 return;
4644 // Methods must have a body unless they're extern or abstract
4646 if (block == null) {
4647 Report.Error (
4648 501, method.Location, "Method `" +
4649 TypeManager.CSharpSignature (builder) +
4650 "' must declare a body since it is not marked " +
4651 "abstract or extern");
4652 return;
4655 SourceMethod source = SourceMethod.Create (
4656 container, MethodBuilder, method.Block);
4659 // Handle destructors specially
4661 // FIXME: This code generates buggy code
4663 if (member is Destructor)
4664 EmitDestructor (ec, block);
4665 else
4666 ec.EmitTopBlock (block, ParameterInfo, loc);
4668 if (source != null)
4669 source.CloseMethod ();
4672 void EmitDestructor (EmitContext ec, ToplevelBlock block)
4674 ILGenerator ig = ec.ig;
4676 Label finish = ig.DefineLabel ();
4678 block.SetDestructor ();
4680 ig.BeginExceptionBlock ();
4681 ec.ReturnLabel = finish;
4682 ec.HasReturnLabel = true;
4683 ec.EmitTopBlock (block, null, method.Location);
4685 // ig.MarkLabel (finish);
4686 ig.BeginFinallyBlock ();
4688 if (ec.ContainerType.BaseType != null) {
4689 Expression member_lookup = Expression.MemberLookup (
4690 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4691 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4693 if (member_lookup != null){
4694 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4696 ig.Emit (OpCodes.Ldarg_0);
4697 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4701 ig.EndExceptionBlock ();
4702 //ig.MarkLabel (ec.ReturnLabel);
4703 ig.Emit (OpCodes.Ret);
4707 public class Destructor : Method {
4709 public Destructor (TypeContainer ds, Expression return_type, int mod,
4710 string name, Parameters parameters, Attributes attrs,
4711 Location l)
4712 : base (ds, return_type, mod, false, new MemberName (name),
4713 parameters, attrs, l)
4716 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4718 if (a.Type == TypeManager.conditional_attribute_type) {
4719 Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
4720 return;
4723 base.ApplyAttributeBuilder (a, cb);
4727 abstract public class MemberBase : MemberCore {
4728 public Expression Type;
4730 public MethodAttributes flags;
4732 protected readonly int explicit_mod_flags;
4735 // The "short" name of this property / indexer / event. This is the
4736 // name without the explicit interface.
4738 public string ShortName;
4741 // The type of this property / indexer / event
4743 public Type MemberType;
4746 // If true, this is an explicit interface implementation
4748 public bool IsExplicitImpl = false;
4751 // The name of the interface we are explicitly implementing
4753 public MemberName ExplicitInterfaceName = null;
4756 // Whether this is an interface member.
4758 public bool IsInterface;
4761 // If true, the interface type we are explicitly implementing
4763 public Type InterfaceType = null;
4766 // The constructor is only exposed to our children
4768 protected MemberBase (TypeContainer parent, Expression type, int mod,
4769 int allowed_mod, int def_mod, MemberName name,
4770 Attributes attrs, Location loc)
4771 : base (parent, name, attrs, loc)
4773 explicit_mod_flags = mod;
4774 Type = type;
4775 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4777 // Check for explicit interface implementation
4778 if (MemberName.Left != null) {
4779 ExplicitInterfaceName = MemberName.Left;
4780 ShortName = MemberName.Name;
4781 IsExplicitImpl = true;
4782 } else
4783 ShortName = Name;
4786 protected virtual bool CheckBase ()
4788 if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.Kind == Kind.Struct) {
4789 Report.Error (666, Location, "Protected member in struct declaration");
4790 return false;
4793 if ((RootContext.WarningLevel >= 4) &&
4794 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
4795 ((ModFlags & Modifiers.PROTECTED) != 0) &&
4796 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
4797 Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
4799 return true;
4802 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4804 bool error = false;
4806 foreach (Type partype in parameters){
4807 if (partype == TypeManager.void_type) {
4808 Report.Error (
4809 1547, Location, "Keyword 'void' cannot " +
4810 "be used in this context");
4811 return false;
4814 if (partype.IsPointer){
4815 if (!UnsafeOK (ds))
4816 error = true;
4817 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4818 error = true;
4821 if (ds.AsAccessible (partype, ModFlags))
4822 continue;
4824 if (this is Indexer)
4825 Report.Error (55, Location,
4826 "Inconsistent accessibility: parameter type `" +
4827 TypeManager.CSharpName (partype) + "' is less " +
4828 "accessible than indexer `" + Name + "'");
4829 else if ((this is Method) && ((Method) this).IsOperator)
4830 Report.Error (57, Location,
4831 "Inconsistent accessibility: parameter type `" +
4832 TypeManager.CSharpName (partype) + "' is less " +
4833 "accessible than operator `" + Name + "'");
4834 else
4835 Report.Error (51, Location,
4836 "Inconsistent accessibility: parameter type `" +
4837 TypeManager.CSharpName (partype) + "' is less " +
4838 "accessible than method `" + Name + "'");
4839 error = true;
4842 return !error;
4845 protected virtual bool DoDefine ()
4847 EmitContext ec = Parent.EmitContext;
4848 if (ec == null)
4849 throw new InternalErrorException ("MemberBase.DoDefine called too early");
4851 if (Name == null)
4852 throw new InternalErrorException ();
4854 if (IsInterface) {
4855 ModFlags = Modifiers.PUBLIC |
4856 Modifiers.ABSTRACT |
4857 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
4859 flags = MethodAttributes.Public |
4860 MethodAttributes.Abstract |
4861 MethodAttributes.HideBySig |
4862 MethodAttributes.NewSlot |
4863 MethodAttributes.Virtual;
4864 } else {
4865 if (!Parent.MethodModifiersValid (ModFlags, Name, Location))
4866 return false;
4868 flags = Modifiers.MethodAttr (ModFlags);
4871 // Lookup Type, verify validity
4872 bool old_unsafe = ec.InUnsafe;
4873 ec.InUnsafe = InUnsafe;
4874 Type = Type.ResolveAsTypeTerminal (ec, false);
4875 ec.InUnsafe = old_unsafe;
4877 if (Type == null)
4878 return false;
4880 MemberType = Type.Type;
4882 if ((Parent.ModFlags & Modifiers.SEALED) != 0){
4883 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4884 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4885 return false;
4889 // verify accessibility
4890 if (!Parent.AsAccessible (MemberType, ModFlags)) {
4891 if (this is Property)
4892 Report.Error (53, Location,
4893 "Inconsistent accessibility: property type `" +
4894 TypeManager.CSharpName (MemberType) + "' is less " +
4895 "accessible than property `" + Name + "'");
4896 else if (this is Indexer)
4897 Report.Error (54, Location,
4898 "Inconsistent accessibility: indexer return type `" +
4899 TypeManager.CSharpName (MemberType) + "' is less " +
4900 "accessible than indexer `" + Name + "'");
4901 else if (this is Method) {
4902 if (((Method) this).IsOperator)
4903 Report.Error (56, Location,
4904 "Inconsistent accessibility: return type `" +
4905 TypeManager.CSharpName (MemberType) + "' is less " +
4906 "accessible than operator `" + Name + "'");
4907 else
4908 Report.Error (50, Location,
4909 "Inconsistent accessibility: return type `" +
4910 TypeManager.CSharpName (MemberType) + "' is less " +
4911 "accessible than method `" + Name + "'");
4912 } else
4913 Report.Error (52, Location,
4914 "Inconsistent accessibility: field type `" +
4915 TypeManager.CSharpName (MemberType) + "' is less " +
4916 "accessible than field `" + Name + "'");
4917 return false;
4920 if (MemberType.IsPointer && !UnsafeOK (Parent))
4921 return false;
4923 if (IsExplicitImpl) {
4924 Expression expr = ExplicitInterfaceName.GetTypeExpression (Location);
4925 TypeExpr texpr = expr.ResolveAsTypeTerminal (ec, false);
4926 if (texpr == null)
4927 return false;
4929 InterfaceType = texpr.ResolveType (ec);
4931 if (InterfaceType.IsClass) {
4932 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4933 return false;
4936 #if FIXME
4937 // Compute the full name that we need to export.
4938 if (InterfaceType.FullName != ExplicitInterfaceName) {
4939 ExplicitInterfaceName = InterfaceType.FullName;
4940 UpdateMemberName ();
4942 #endif
4944 if (!Parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
4945 return false;
4947 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4950 return true;
4953 /// <summary>
4954 /// The name of the member can be changed during definition (see IndexerName attribute)
4955 /// </summary>
4956 protected virtual void UpdateMemberName ()
4958 MemberName.Name = ShortName;
4961 public override string GetSignatureForError (TypeContainer tc)
4963 return String.Concat (tc.Name, '.', base.GetSignatureForError (tc));
4966 protected bool IsTypePermitted ()
4968 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
4969 Report.Error (610, Location, "Field or property cannot be of type '{0}'", TypeManager.CSharpName (MemberType));
4970 return false;
4972 return true;
4975 protected override bool VerifyClsCompliance(DeclSpace ds)
4977 if (base.VerifyClsCompliance (ds)) {
4978 return true;
4981 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4982 Report.Error (3010, Location, "'{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
4984 return false;
4987 protected override void VerifyObsoleteAttribute()
4989 CheckUsageOfObsoleteAttribute (MemberType);
4994 // Fields and Events both generate FieldBuilders, we use this to share
4995 // their common bits. This is also used to flag usage of the field
4997 abstract public class FieldBase : MemberBase {
4998 public FieldBuilder FieldBuilder;
4999 public Status status;
5001 [Flags]
5002 public enum Status : byte {
5003 ASSIGNED = 1,
5004 USED = 2
5007 static string[] attribute_targets = new string [] { "field" };
5009 /// <summary>
5010 /// Symbol with same name in parent class/struct
5011 /// </summary>
5012 public MemberInfo conflict_symbol;
5015 // The constructor is only exposed to our children
5017 protected FieldBase (TypeContainer parent, Expression type, int mod,
5018 int allowed_mod, MemberName name, object init,
5019 Attributes attrs, Location loc)
5020 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
5021 name, attrs, loc)
5023 this.init = init;
5026 public override AttributeTargets AttributeTargets {
5027 get {
5028 return AttributeTargets.Field;
5032 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5034 if (a.Type == TypeManager.marshal_as_attr_type) {
5035 UnmanagedMarshal marshal = a.GetMarshal (this);
5036 if (marshal != null) {
5037 FieldBuilder.SetMarshal (marshal);
5039 return;
5042 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5043 a.Error_InvalidSecurityParent ();
5044 return;
5047 FieldBuilder.SetCustomAttribute (cb);
5051 // Whether this field has an initializer.
5053 public bool HasInitializer {
5054 get {
5055 return init != null;
5059 protected readonly Object init;
5061 // Private.
5062 Expression init_expr;
5063 bool init_expr_initialized = false;
5066 // Resolves and returns the field initializer.
5068 public Expression GetInitializerExpression (EmitContext ec)
5070 if (init_expr_initialized)
5071 return init_expr;
5073 Expression e;
5074 if (init is Expression)
5075 e = (Expression) init;
5076 else
5077 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
5079 ec.IsFieldInitializer = true;
5080 e = e.DoResolve (ec);
5081 ec.IsFieldInitializer = false;
5083 init_expr = e;
5084 init_expr_initialized = true;
5086 return init_expr;
5089 protected override bool CheckBase ()
5091 if (!base.CheckBase ())
5092 return false;
5094 // TODO: Implement
5095 if (IsInterface)
5096 return true;
5098 conflict_symbol = Parent.FindMemberWithSameName (Name, false);
5099 if (conflict_symbol == null) {
5100 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5101 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
5103 return true;
5106 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5107 Report.SymbolRelatedToPreviousError (conflict_symbol);
5108 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
5111 return true;
5114 protected override bool DoDefine ()
5116 if (!base.DoDefine ())
5117 return false;
5119 if (MemberType == TypeManager.void_type) {
5120 Report.Error (1547, Location,
5121 "Keyword 'void' cannot be used in this context");
5122 return false;
5124 return true;
5127 public override string GetSignatureForError ()
5129 if (FieldBuilder == null) {
5130 return base.GetSignatureForError (Parent);
5132 return TypeManager.GetFullNameSignature (FieldBuilder);
5135 public override string[] ValidAttributeTargets {
5136 get {
5137 return attribute_targets;
5141 protected override bool VerifyClsCompliance (DeclSpace ds)
5143 if (!base.VerifyClsCompliance (ds))
5144 return false;
5146 if (FieldBuilder == null) {
5147 return true;
5150 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
5151 Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
5153 return true;
5157 public void SetAssigned ()
5159 status |= Status.ASSIGNED;
5163 public abstract class FieldMember: FieldBase
5165 bool has_field_offset = false;
5167 protected FieldMember (TypeContainer parent, Expression type, int mod,
5168 int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
5169 : base (parent, type, mod, allowed_mod, name, init, attrs, loc)
5173 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5175 if (a.Type == TypeManager.field_offset_attribute_type)
5177 has_field_offset = true;
5179 if (!Parent.HasExplicitLayout) {
5180 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5181 return;
5184 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5185 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5186 return;
5189 base.ApplyAttributeBuilder (a, cb);
5193 public override bool Define()
5195 EmitContext ec = Parent.EmitContext;
5196 if (ec == null)
5197 throw new InternalErrorException ("FieldMember.Define called too early");
5199 bool old_unsafe = ec.InUnsafe;
5200 ec.InUnsafe = InUnsafe;
5201 TypeExpr texpr = Type.ResolveAsTypeTerminal (ec, false);
5202 if (texpr == null)
5203 return false;
5205 MemberType = texpr.ResolveType (ec);
5206 ec.InUnsafe = old_unsafe;
5208 if (!CheckBase ())
5209 return false;
5211 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5212 Report.Error (52, Location,
5213 "Inconsistent accessibility: field type `" +
5214 TypeManager.CSharpName (MemberType) + "' is less " +
5215 "accessible than field `" + Name + "'");
5216 return false;
5219 if (!IsTypePermitted ())
5220 return false;
5222 if (MemberType.IsPointer && !UnsafeOK (Parent))
5223 return false;
5225 return true;
5228 public override void Emit ()
5230 if (Parent.HasExplicitLayout && !has_field_offset && (ModFlags & Modifiers.STATIC) == 0) {
5231 Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5234 base.Emit ();
5239 // The Field class is used to represents class/struct fields during parsing.
5241 public class Field : FieldMember {
5242 // <summary>
5243 // Modifiers allowed in a class declaration
5244 // </summary>
5245 const int AllowedModifiers =
5246 Modifiers.NEW |
5247 Modifiers.PUBLIC |
5248 Modifiers.PROTECTED |
5249 Modifiers.INTERNAL |
5250 Modifiers.PRIVATE |
5251 Modifiers.STATIC |
5252 Modifiers.VOLATILE |
5253 Modifiers.UNSAFE |
5254 Modifiers.READONLY;
5256 public Field (TypeContainer parent, Expression type, int mod, string name,
5257 Object expr_or_array_init, Attributes attrs, Location loc)
5258 : base (parent, type, mod, AllowedModifiers, new MemberName (name),
5259 expr_or_array_init, attrs, loc)
5263 public override bool Define ()
5265 if (!base.Define ())
5266 return false;
5268 if (RootContext.WarningLevel > 1){
5269 Type ptype = Parent.TypeBuilder.BaseType;
5271 // ptype is only null for System.Object while compiling corlib.
5272 if (ptype != null){
5273 TypeContainer.FindMembers (
5274 ptype, MemberTypes.Method,
5275 BindingFlags.Public |
5276 BindingFlags.Static | BindingFlags.Instance,
5277 System.Type.FilterName, Name);
5281 if ((ModFlags & Modifiers.VOLATILE) != 0){
5282 if (!MemberType.IsClass){
5283 Type vt = MemberType;
5285 if (TypeManager.IsEnumType (vt))
5286 vt = TypeManager.EnumToUnderlying (MemberType);
5288 if (!((vt == TypeManager.bool_type) ||
5289 (vt == TypeManager.sbyte_type) ||
5290 (vt == TypeManager.byte_type) ||
5291 (vt == TypeManager.short_type) ||
5292 (vt == TypeManager.ushort_type) ||
5293 (vt == TypeManager.int32_type) ||
5294 (vt == TypeManager.uint32_type) ||
5295 (vt == TypeManager.char_type) ||
5296 (vt == TypeManager.float_type) ||
5297 (!vt.IsValueType))){
5298 Report.Error (
5299 677, Location, Parent.MakeName (Name) +
5300 " A volatile field can not be of type `" +
5301 TypeManager.CSharpName (vt) + "'");
5302 return false;
5306 if ((ModFlags & Modifiers.READONLY) != 0){
5307 Report.Error (
5308 678, Location,
5309 "A field can not be both volatile and readonly");
5310 return false;
5314 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5316 if (Parent.Kind == Kind.Struct &&
5317 ((fa & FieldAttributes.Static) == 0) &&
5318 MemberType == Parent.TypeBuilder &&
5319 !TypeManager.IsBuiltinType (MemberType)){
5320 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
5321 "' causes a cycle in the structure layout");
5322 return false;
5325 try {
5326 FieldBuilder = Parent.TypeBuilder.DefineField (
5327 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5329 TypeManager.RegisterFieldBase (FieldBuilder, this);
5331 catch (ArgumentException) {
5332 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5333 return false;
5336 return true;
5339 public override void Emit ()
5341 if (OptAttributes != null) {
5342 EmitContext ec = new EmitContext (
5343 Parent, Location, null, FieldBuilder.FieldType,
5344 ModFlags);
5345 OptAttributes.Emit (ec, this);
5348 base.Emit ();
5353 // `set' and `get' accessors are represented with an Accessor.
5355 public class Accessor {
5357 // Null if the accessor is empty, or a Block if not
5359 public const int AllowedModifiers =
5360 Modifiers.PUBLIC |
5361 Modifiers.PROTECTED |
5362 Modifiers.INTERNAL |
5363 Modifiers.PRIVATE;
5365 public ToplevelBlock Block;
5366 public Attributes Attributes;
5367 public Location Location;
5368 public int ModFlags;
5370 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5372 Block = b;
5373 Attributes = attrs;
5374 Location = loc;
5375 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5380 // Ooouh Martin, templates are missing here.
5381 // When it will be possible move here a lot of child code and template method type.
5382 public abstract class AbstractPropertyEventMethod: MemberCore, IMethodData {
5383 protected MethodData method_data;
5384 protected ToplevelBlock block;
5385 protected ListDictionary declarative_security;
5387 // The accessor are created event if they are not wanted.
5388 // But we need them because their names are reserved.
5389 // Field says whether accessor will be emited or not
5390 public readonly bool IsDummy;
5392 protected readonly string prefix;
5394 ReturnParameter return_attributes;
5396 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5397 : base (null, SetupName (prefix, member), null, member.Location)
5399 this.prefix = prefix;
5400 IsDummy = true;
5403 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5404 string prefix)
5405 : base (null, SetupName (prefix, member),
5406 accessor.Attributes, accessor.Location)
5408 this.prefix = prefix;
5409 this.block = accessor.Block;
5412 static MemberName SetupName (string prefix, MemberBase member)
5414 MemberName name = member.MemberName.Clone ();
5415 name.Name = prefix + member.ShortName;
5416 return name;
5419 public void UpdateName (MemberBase member)
5421 MemberName.Name = prefix + member.ShortName;
5424 #region IMethodData Members
5426 public ToplevelBlock Block {
5427 get {
5428 return block;
5431 set {
5432 block = value;
5436 public CallingConventions CallingConventions {
5437 get {
5438 return CallingConventions.Standard;
5442 public bool IsExcluded (EmitContext ec)
5444 return false;
5447 public MemberName MethodName {
5448 get {
5449 return MemberName;
5453 public abstract ObsoleteAttribute GetObsoleteAttribute ();
5454 public abstract Type[] ParameterTypes { get; }
5455 public abstract Type ReturnType { get; }
5456 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
5458 #endregion
5460 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5462 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5463 a.Type == TypeManager.conditional_attribute_type) {
5464 Report.Error (1667, a.Location, "'{0}' is not valid on property or event accessors. It is valid on '{1}' declarations only", TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5465 return;
5468 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
5469 if (declarative_security == null)
5470 declarative_security = new ListDictionary ();
5471 a.ExtractSecurityPermissionSet (declarative_security);
5472 return;
5475 if (a.Target == AttributeTargets.Method) {
5476 method_data.MethodBuilder.SetCustomAttribute (cb);
5477 return;
5480 if (a.Target == AttributeTargets.ReturnValue) {
5481 if (return_attributes == null)
5482 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5484 return_attributes.ApplyAttributeBuilder (a, cb);
5485 return;
5488 ApplyToExtraTarget (a, cb);
5491 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5493 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5496 public override bool Define()
5498 return false;
5501 public virtual void Emit (TypeContainer container)
5503 method_data.Emit (container, this);
5505 if (declarative_security != null) {
5506 foreach (DictionaryEntry de in declarative_security) {
5507 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5511 block = null;
5514 public override bool IsClsCompliaceRequired(DeclSpace ds)
5516 return false;
5519 public bool IsDuplicateImplementation (MethodCore method)
5521 if (Name != method.Name)
5522 return false;
5524 Type[] param_types = method.ParameterTypes;
5526 if (param_types.Length != ParameterTypes.Length)
5527 return false;
5529 for (int i = 0; i < param_types.Length; i++)
5530 if (param_types [i] != ParameterTypes [i])
5531 return false;
5533 Report.SymbolRelatedToPreviousError (method);
5534 Report.Error (111, Location, TypeContainer.Error111, method.Parent.GetSignatureForError (), Name);
5535 return true;
5538 public new Location Location {
5539 get {
5540 return base.Location;
5544 protected override void VerifyObsoleteAttribute()
5551 // Properties and Indexers both generate PropertyBuilders, we use this to share
5552 // their common bits.
5554 abstract public class PropertyBase : MethodCore {
5556 public class GetMethod: PropertyMethod
5558 static string[] attribute_targets = new string [] { "method", "return" };
5560 public GetMethod (MethodCore method):
5561 base (method, "get_")
5565 public GetMethod (MethodCore method, Accessor accessor):
5566 base (method, accessor, "get_")
5570 public override MethodBuilder Define(TypeContainer container)
5572 base.Define (container);
5574 method_data = new MethodData (method, method.ParameterInfo, ModFlags, flags, this);
5576 if (!method_data.Define (container))
5577 return null;
5579 return method_data.MethodBuilder;
5582 public override string GetSignatureForError (TypeContainer tc)
5584 return String.Concat (base.GetSignatureForError (tc), ".get");
5587 public override Type ReturnType {
5588 get {
5589 return method.MemberType;
5593 public override string[] ValidAttributeTargets {
5594 get {
5595 return attribute_targets;
5600 public class SetMethod: PropertyMethod {
5602 static string[] attribute_targets = new string [] { "method", "param", "return" };
5603 ImplicitParameter param_attr;
5605 public SetMethod (MethodCore method):
5606 base (method, "set_")
5610 public SetMethod (MethodCore method, Accessor accessor):
5611 base (method, accessor, "set_")
5615 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5617 if (a.Target == AttributeTargets.Parameter) {
5618 if (param_attr == null)
5619 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5621 param_attr.ApplyAttributeBuilder (a, cb);
5622 return;
5625 base.ApplyAttributeBuilder (a, cb);
5628 protected virtual InternalParameters GetParameterInfo (EmitContext ec)
5630 Parameter [] parms = new Parameter [1];
5631 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
5632 Parameters parameters = new Parameters (parms, null, method.Location);
5633 Type [] types = parameters.GetParameterInfo (ec);
5634 return new InternalParameters (types, parameters);
5637 public override MethodBuilder Define(TypeContainer container)
5639 if (container.EmitContext == null)
5640 throw new InternalErrorException ("SetMethod.Define called too early");
5642 base.Define (container);
5644 method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
5646 if (!method_data.Define (container))
5647 return null;
5649 return method_data.MethodBuilder;
5652 public override string GetSignatureForError (TypeContainer tc)
5654 return String.Concat (base.GetSignatureForError (tc), ".set");
5657 public override Type[] ParameterTypes {
5658 get {
5659 return new Type[] { method.MemberType };
5663 public override Type ReturnType {
5664 get {
5665 return TypeManager.void_type;
5669 public override string[] ValidAttributeTargets {
5670 get {
5671 return attribute_targets;
5676 static string[] attribute_targets = new string [] { "property" };
5678 public abstract class PropertyMethod: AbstractPropertyEventMethod
5680 protected readonly MethodCore method;
5681 protected MethodAttributes flags;
5683 public PropertyMethod (MethodCore method, string prefix)
5684 : base (method, prefix)
5686 this.method = method;
5689 public PropertyMethod (MethodCore method, Accessor accessor,
5690 string prefix)
5691 : base (method, accessor, prefix)
5693 this.method = method;
5694 this.ModFlags = accessor.ModFlags;
5696 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
5697 Report.FeatureIsNotStandardized (Location, "accessor modifiers");
5698 Environment.Exit (1);
5702 public override AttributeTargets AttributeTargets {
5703 get {
5704 return AttributeTargets.Method;
5708 public override bool IsClsCompliaceRequired(DeclSpace ds)
5710 return method.IsClsCompliaceRequired (ds);
5713 public InternalParameters ParameterInfo
5715 get {
5716 return method_data.ParameterInfo;
5720 public virtual MethodBuilder Define (TypeContainer container)
5723 // Check for custom access modifier
5725 if (ModFlags == 0) {
5726 ModFlags = method.ModFlags;
5727 flags = method.flags;
5728 } else {
5729 CheckModifiers (container, ModFlags);
5730 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
5731 flags = Modifiers.MethodAttr (ModFlags);
5732 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
5735 return null;
5739 public override Type[] ParameterTypes {
5740 get {
5741 return TypeManager.NoTypes;
5745 public override EmitContext CreateEmitContext (TypeContainer tc,
5746 ILGenerator ig)
5748 return new EmitContext (
5749 tc, method.Parent, method.Location, ig, ReturnType,
5750 method.ModFlags, false);
5753 public override ObsoleteAttribute GetObsoleteAttribute ()
5755 return method.GetObsoleteAttribute (method.Parent);
5758 public override string GetSignatureForError (TypeContainer tc)
5760 return String.Concat (tc.Name, '.', method.Name);
5763 void CheckModifiers (TypeContainer container, int modflags)
5765 int flags = 0;
5766 int mflags = method.ModFlags & Modifiers.Accessibility;
5768 if ((mflags & Modifiers.PUBLIC) != 0) {
5769 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
5771 else if ((mflags & Modifiers.PROTECTED) != 0) {
5772 if ((mflags & Modifiers.INTERNAL) != 0)
5773 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
5775 flags |= Modifiers.PRIVATE;
5777 else if ((mflags & Modifiers.INTERNAL) != 0)
5778 flags |= Modifiers.PRIVATE;
5780 if ((mflags == modflags) || (modflags & (~flags)) != 0)
5781 Report.Error (273, Location, "{0}: accessibility modifier must be more restrictive than the property or indexer",
5782 GetSignatureForError (container));
5788 public PropertyMethod Get, Set;
5789 public PropertyBuilder PropertyBuilder;
5790 public MethodBuilder GetBuilder, SetBuilder;
5792 protected EmitContext ec;
5794 public PropertyBase (TypeContainer ds, Expression type, int mod_flags,
5795 int allowed_mod, bool is_iface, MemberName name,
5796 Parameters parameters, Attributes attrs,
5797 Location loc)
5798 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
5799 attrs, parameters, loc)
5803 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5805 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5806 a.Error_InvalidSecurityParent ();
5807 return;
5810 PropertyBuilder.SetCustomAttribute (cb);
5813 public override AttributeTargets AttributeTargets {
5814 get {
5815 return AttributeTargets.Property;
5819 public override bool Define ()
5821 if (!DoDefine ())
5822 return false;
5824 if (!IsTypePermitted ())
5825 return false;
5827 return true;
5830 protected override bool DoDefine ()
5832 if (!base.DoDefine ())
5833 return false;
5836 // Accessors modifiers check
5838 if (Get.ModFlags != 0 && Set.ModFlags != 0) {
5839 Report.Error (274, Location, "'{0}': cannot specify accessibility modifiers for both accessors of the property or indexer.",
5840 GetSignatureForError ());
5841 return false;
5844 if ((Get.IsDummy || Set.IsDummy)
5845 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
5846 Report.Error (276, Location,
5847 "'{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor.",
5848 GetSignatureForError ());
5849 return false;
5852 if (MemberType.IsAbstract && MemberType.IsSealed) {
5853 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
5854 return false;
5857 ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
5858 return true;
5861 public override string GetSignatureForError()
5863 if (PropertyBuilder == null)
5864 return GetSignatureForError (Parent);
5866 return TypeManager.CSharpSignature (PropertyBuilder, false);
5870 protected override bool CheckForDuplications ()
5872 ArrayList ar = Parent.Indexers;
5873 if (ar != null) {
5874 int arLen = ar.Count;
5876 for (int i = 0; i < arLen; i++) {
5877 Indexer m = (Indexer) ar [i];
5878 if (IsDuplicateImplementation (m))
5879 return false;
5883 ar = Parent.Properties;
5884 if (ar != null) {
5885 int arLen = ar.Count;
5887 for (int i = 0; i < arLen; i++) {
5888 Property m = (Property) ar [i];
5889 if (IsDuplicateImplementation (m))
5890 return false;
5894 return true;
5897 // TODO: rename to Resolve......
5898 protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
5900 PropertyInfo parent_property = container.ParentContainer.MemberCache.FindMemberToOverride (
5901 container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
5903 if (parent_property == null)
5904 return null;
5906 parent_ret_type = parent_property.PropertyType;
5907 MethodInfo get_accessor = parent_property.GetGetMethod (true);
5908 MethodInfo set_accessor = parent_property.GetSetMethod (true);
5909 MethodAttributes get_accessor_access, set_accessor_access;
5911 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
5912 if (Get != null && !Get.IsDummy && get_accessor == null) {
5913 Report.SymbolRelatedToPreviousError (parent_property);
5914 Report.Error (545, Location, "'{0}': cannot override because '{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (parent_property));
5917 if (Set != null && !Set.IsDummy && set_accessor == null) {
5918 Report.SymbolRelatedToPreviousError (parent_property);
5919 Report.Error (546, Location, "'{0}': cannot override because '{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (parent_property));
5924 // Check parent accessors access
5926 get_accessor_access = set_accessor_access = 0;
5927 if ((ModFlags & Modifiers.NEW) == 0) {
5928 if (get_accessor != null) {
5929 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
5930 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
5932 if (!Get.IsDummy && (get_accessor_access) !=
5933 (get_flags & MethodAttributes.MemberAccessMask))
5934 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
5935 GetSignatureForError (), TypeManager.GetFullNameSignature (parent_property));
5938 if (set_accessor != null) {
5939 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
5940 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
5942 if (!Set.IsDummy & (set_accessor_access) !=
5943 (set_flags & MethodAttributes.MemberAccessMask))
5944 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
5945 GetSignatureForError (container), TypeManager.GetFullNameSignature (parent_property));
5950 // Get the less restrictive access
5952 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
5955 public override void Emit ()
5958 // The PropertyBuilder can be null for explicit implementations, in that
5959 // case, we do not actually emit the ".property", so there is nowhere to
5960 // put the attribute
5962 if (PropertyBuilder != null && OptAttributes != null)
5963 OptAttributes.Emit (ec, this);
5965 if (!Get.IsDummy)
5966 Get.Emit (Parent);
5968 if (!Set.IsDummy)
5969 Set.Emit (Parent);
5971 base.Emit ();
5974 /// <summary>
5975 /// Tests whether accessors are not in collision with some method (CS0111)
5976 /// </summary>
5977 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
5979 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
5982 protected override void UpdateMemberName ()
5984 base.UpdateMemberName ();
5986 Get.UpdateName (this);
5987 Set.UpdateName (this);
5991 public override string[] ValidAttributeTargets {
5992 get {
5993 return attribute_targets;
5998 public class Property : PropertyBase, IIteratorContainer {
5999 const int AllowedModifiers =
6000 Modifiers.NEW |
6001 Modifiers.PUBLIC |
6002 Modifiers.PROTECTED |
6003 Modifiers.INTERNAL |
6004 Modifiers.PRIVATE |
6005 Modifiers.STATIC |
6006 Modifiers.SEALED |
6007 Modifiers.OVERRIDE |
6008 Modifiers.ABSTRACT |
6009 Modifiers.UNSAFE |
6010 Modifiers.EXTERN |
6011 Modifiers.METHOD_YIELDS |
6012 Modifiers.VIRTUAL;
6014 const int AllowedInterfaceModifiers =
6015 Modifiers.NEW;
6017 public Property (TypeContainer ds, Expression type, int mod, bool is_iface,
6018 MemberName name, Attributes attrs, Accessor get_block,
6019 Accessor set_block, Location loc)
6020 : base (ds, type, mod,
6021 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6022 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
6023 loc)
6025 if (get_block == null)
6026 Get = new GetMethod (this);
6027 else
6028 Get = new GetMethod (this, get_block);
6030 if (set_block == null)
6031 Set = new SetMethod (this);
6032 else
6033 Set = new SetMethod (this, set_block);
6036 public override bool Define ()
6038 if (!base.Define ())
6039 return false;
6041 if (!CheckBase ())
6042 return false;
6044 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6046 if (!Get.IsDummy) {
6048 GetBuilder = Get.Define (Parent);
6049 if (GetBuilder == null)
6050 return false;
6053 // Setup iterator if we are one
6055 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
6056 Iterator iterator = new Iterator (
6057 Parent, "get", MemberType,
6058 TypeManager.NoTypes, Get.ParameterInfo,
6059 ModFlags, Get.Block, Location);
6061 if (!iterator.DefineIterator ())
6062 return false;
6063 Get.Block = iterator.Block;
6067 if (!Set.IsDummy) {
6068 SetBuilder = Set.Define (Parent);
6069 if (SetBuilder == null)
6070 return false;
6072 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
6075 // FIXME - PropertyAttributes.HasDefault ?
6077 PropertyAttributes prop_attr = PropertyAttributes.None;
6078 if (!IsInterface)
6079 prop_attr |= PropertyAttributes.RTSpecialName |
6080 PropertyAttributes.SpecialName;
6082 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6083 Name, prop_attr, MemberType, null);
6085 if (!Get.IsDummy)
6086 PropertyBuilder.SetGetMethod (GetBuilder);
6088 if (!Set.IsDummy)
6089 PropertyBuilder.SetSetMethod (SetBuilder);
6091 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
6092 return true;
6095 public void SetYields ()
6097 ModFlags |= Modifiers.METHOD_YIELDS;
6101 /// </summary>
6102 /// Gigantic workaround for lameness in SRE follows :
6103 /// This class derives from EventInfo and attempts to basically
6104 /// wrap around the EventBuilder so that FindMembers can quickly
6105 /// return this in it search for members
6106 /// </summary>
6107 public class MyEventBuilder : EventInfo {
6110 // We use this to "point" to our Builder which is
6111 // not really a MemberInfo
6113 EventBuilder MyBuilder;
6116 // We "catch" and wrap these methods
6118 MethodInfo raise, remove, add;
6120 EventAttributes attributes;
6121 Type declaring_type, reflected_type, event_type;
6122 string name;
6124 Event my_event;
6126 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6128 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6130 // And now store the values in our own fields.
6132 declaring_type = type_builder;
6134 reflected_type = type_builder;
6136 attributes = event_attr;
6137 this.name = name;
6138 my_event = ev;
6139 this.event_type = event_type;
6143 // Methods that you have to override. Note that you only need
6144 // to "implement" the variants that take the argument (those are
6145 // the "abstract" methods, the others (GetAddMethod()) are
6146 // regular.
6148 public override MethodInfo GetAddMethod (bool nonPublic)
6150 return add;
6153 public override MethodInfo GetRemoveMethod (bool nonPublic)
6155 return remove;
6158 public override MethodInfo GetRaiseMethod (bool nonPublic)
6160 return raise;
6164 // These methods make "MyEventInfo" look like a Builder
6166 public void SetRaiseMethod (MethodBuilder raiseMethod)
6168 raise = raiseMethod;
6169 MyBuilder.SetRaiseMethod (raiseMethod);
6172 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6174 remove = removeMethod;
6175 MyBuilder.SetRemoveOnMethod (removeMethod);
6178 public void SetAddOnMethod (MethodBuilder addMethod)
6180 add = addMethod;
6181 MyBuilder.SetAddOnMethod (addMethod);
6184 public void SetCustomAttribute (CustomAttributeBuilder cb)
6186 MyBuilder.SetCustomAttribute (cb);
6189 public override object [] GetCustomAttributes (bool inherit)
6191 // FIXME : There's nothing which can be seemingly done here because
6192 // we have no way of getting at the custom attribute objects of the
6193 // EventBuilder !
6194 return null;
6197 public override object [] GetCustomAttributes (Type t, bool inherit)
6199 // FIXME : Same here !
6200 return null;
6203 public override bool IsDefined (Type t, bool b)
6205 return true;
6208 public override EventAttributes Attributes {
6209 get {
6210 return attributes;
6214 public override string Name {
6215 get {
6216 return name;
6220 public override Type DeclaringType {
6221 get {
6222 return declaring_type;
6226 public override Type ReflectedType {
6227 get {
6228 return reflected_type;
6232 public Type EventType {
6233 get {
6234 return event_type;
6238 public void SetUsed ()
6240 if (my_event != null)
6241 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
6245 /// <summary>
6246 /// For case when event is declared like property (with add and remove accessors).
6247 /// </summary>
6248 public class EventProperty: Event {
6250 static string[] attribute_targets = new string [] { "event", "property" };
6252 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
6253 bool is_iface, MemberName name, Object init,
6254 Attributes attrs, Accessor add, Accessor remove,
6255 Location loc)
6256 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6258 Add = new AddDelegateMethod (this, add);
6259 Remove = new RemoveDelegateMethod (this, remove);
6262 public override string[] ValidAttributeTargets {
6263 get {
6264 return attribute_targets;
6269 /// <summary>
6270 /// Event is declared like field.
6271 /// </summary>
6272 public class EventField: Event {
6274 static string[] attribute_targets = new string [] { "event", "field", "method" };
6276 public EventField (TypeContainer parent, Expression type, int mod_flags,
6277 bool is_iface, MemberName name, Object init,
6278 Attributes attrs, Location loc)
6279 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6281 Add = new AddDelegateMethod (this);
6282 Remove = new RemoveDelegateMethod (this);
6285 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6287 if (a.Target == AttributeTargets.Field) {
6288 FieldBuilder.SetCustomAttribute (cb);
6289 return;
6292 if (a.Target == AttributeTargets.Method) {
6293 AddBuilder.SetCustomAttribute (cb);
6294 RemoveBuilder.SetCustomAttribute (cb);
6295 return;
6298 base.ApplyAttributeBuilder (a, cb);
6301 public override string[] ValidAttributeTargets {
6302 get {
6303 return attribute_targets;
6308 public abstract class Event : FieldBase {
6310 protected sealed class AddDelegateMethod: DelegateMethod
6313 public AddDelegateMethod (Event method):
6314 base (method, "add_")
6318 public AddDelegateMethod (Event method, Accessor accessor):
6319 base (method, accessor, "add_")
6323 protected override MethodInfo DelegateMethodInfo {
6324 get {
6325 return TypeManager.delegate_combine_delegate_delegate;
6331 protected sealed class RemoveDelegateMethod: DelegateMethod
6333 public RemoveDelegateMethod (Event method):
6334 base (method, "remove_")
6338 public RemoveDelegateMethod (Event method, Accessor accessor):
6339 base (method, accessor, "remove_")
6343 protected override MethodInfo DelegateMethodInfo {
6344 get {
6345 return TypeManager.delegate_remove_delegate_delegate;
6351 public abstract class DelegateMethod: AbstractPropertyEventMethod
6353 protected readonly Event method;
6354 ImplicitParameter param_attr;
6356 static string[] attribute_targets = new string [] { "method", "param", "return" };
6358 public DelegateMethod (Event method, string prefix)
6359 : base (method, prefix)
6361 this.method = method;
6364 public DelegateMethod (Event method, Accessor accessor, string prefix)
6365 : base (method, accessor, prefix)
6367 this.method = method;
6370 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6372 if (a.Target == AttributeTargets.Parameter) {
6373 if (param_attr == null)
6374 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6376 param_attr.ApplyAttributeBuilder (a, cb);
6377 return;
6380 base.ApplyAttributeBuilder (a, cb);
6383 public override AttributeTargets AttributeTargets {
6384 get {
6385 return AttributeTargets.Method;
6389 public override bool IsClsCompliaceRequired(DeclSpace ds)
6391 return method.IsClsCompliaceRequired (ds);
6394 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
6396 method_data = new MethodData (method, ip, method.ModFlags,
6397 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6399 if (!method_data.Define (container))
6400 return null;
6402 MethodBuilder mb = method_data.MethodBuilder;
6403 mb.DefineParameter (1, ParameterAttributes.None, "value");
6404 return mb;
6408 public override void Emit (TypeContainer tc)
6410 if (block != null) {
6411 base.Emit (tc);
6412 return;
6415 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6416 EmitContext ec = CreateEmitContext (tc, ig);
6417 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6419 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6420 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6421 ig.Emit (OpCodes.Ldsfld, field_info);
6422 ig.Emit (OpCodes.Ldarg_0);
6423 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6424 ig.Emit (OpCodes.Castclass, method.MemberType);
6425 ig.Emit (OpCodes.Stsfld, field_info);
6426 } else {
6427 ig.Emit (OpCodes.Ldarg_0);
6428 ig.Emit (OpCodes.Ldarg_0);
6429 ig.Emit (OpCodes.Ldfld, field_info);
6430 ig.Emit (OpCodes.Ldarg_1);
6431 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6432 ig.Emit (OpCodes.Castclass, method.MemberType);
6433 ig.Emit (OpCodes.Stfld, field_info);
6435 ig.Emit (OpCodes.Ret);
6438 protected abstract MethodInfo DelegateMethodInfo { get; }
6440 public override Type[] ParameterTypes {
6441 get {
6442 return new Type[] { method.MemberType };
6446 public override Type ReturnType {
6447 get {
6448 return TypeManager.void_type;
6452 public override EmitContext CreateEmitContext (TypeContainer tc,
6453 ILGenerator ig)
6455 return new EmitContext (
6456 tc, method.Parent, Location, ig, ReturnType,
6457 method.ModFlags, false);
6460 public override string GetSignatureForError (TypeContainer tc)
6462 return String.Concat (tc.Name, '.', method.Name);
6465 public override ObsoleteAttribute GetObsoleteAttribute ()
6467 return method.GetObsoleteAttribute (method.Parent);
6470 public override string[] ValidAttributeTargets {
6471 get {
6472 return attribute_targets;
6478 const int AllowedModifiers =
6479 Modifiers.NEW |
6480 Modifiers.PUBLIC |
6481 Modifiers.PROTECTED |
6482 Modifiers.INTERNAL |
6483 Modifiers.PRIVATE |
6484 Modifiers.STATIC |
6485 Modifiers.VIRTUAL |
6486 Modifiers.SEALED |
6487 Modifiers.OVERRIDE |
6488 Modifiers.UNSAFE |
6489 Modifiers.ABSTRACT;
6491 const int AllowedInterfaceModifiers =
6492 Modifiers.NEW;
6494 public DelegateMethod Add, Remove;
6495 public MyEventBuilder EventBuilder;
6496 public MethodBuilder AddBuilder, RemoveBuilder;
6498 public Event (TypeContainer parent, Expression type, int mod_flags,
6499 bool is_iface, MemberName name, Object init, Attributes attrs,
6500 Location loc)
6501 : base (parent, type, mod_flags,
6502 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6503 name, init, attrs, loc)
6505 IsInterface = is_iface;
6508 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6510 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6511 a.Error_InvalidSecurityParent ();
6512 return;
6515 EventBuilder.SetCustomAttribute (cb);
6518 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6520 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
6523 public override AttributeTargets AttributeTargets {
6524 get {
6525 return AttributeTargets.Event;
6529 public override bool Define ()
6531 EventAttributes e_attr;
6532 e_attr = EventAttributes.None;
6534 if (!DoDefine ())
6535 return false;
6537 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
6538 Report.Error (74, Location, "'" + Parent.Name + "." + Name +
6539 "': abstract event can not have an initializer");
6540 return false;
6543 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
6544 Report.Error (66, Location, "'" + Parent.Name + "." + Name +
6545 "' : event must be of a delegate type");
6546 return false;
6549 EmitContext ec = Parent.EmitContext;
6550 if (ec == null)
6551 throw new InternalErrorException ("Event.Define called too early?");
6552 bool old_unsafe = ec.InUnsafe;
6553 ec.InUnsafe = InUnsafe;
6555 Parameter [] parms = new Parameter [1];
6556 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
6557 Parameters parameters = new Parameters (parms, null, Location);
6558 Type [] types = parameters.GetParameterInfo (ec);
6559 InternalParameters ip = new InternalParameters (types, parameters);
6561 ec.InUnsafe = old_unsafe;
6563 if (!CheckBase ())
6564 return false;
6567 // Now define the accessors
6570 AddBuilder = Add.Define (Parent, ip);
6571 if (AddBuilder == null)
6572 return false;
6574 RemoveBuilder = Remove.Define (Parent, ip);
6575 if (RemoveBuilder == null)
6576 return false;
6578 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
6580 if (Add.Block == null && Remove.Block == null && !IsInterface) {
6581 FieldBuilder = Parent.TypeBuilder.DefineField (
6582 Name, MemberType,
6583 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6584 TypeManager.RegisterPrivateFieldOfEvent (
6585 (EventInfo) EventBuilder, FieldBuilder);
6586 TypeManager.RegisterFieldBase (FieldBuilder, this);
6589 EventBuilder.SetAddOnMethod (AddBuilder);
6590 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6592 TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
6593 return true;
6596 protected override bool CheckBase ()
6598 if (!base.CheckBase ())
6599 return false;
6601 if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
6602 if (!(conflict_symbol is EventInfo)) {
6603 Report.SymbolRelatedToPreviousError (conflict_symbol);
6604 Report.Error (72, Location, "Event '{0}' can override only event", GetSignatureForError (Parent));
6605 return false;
6609 return true;
6612 public override void Emit ()
6614 if (OptAttributes != null) {
6615 EmitContext ec = new EmitContext (
6616 Parent, Location, null, MemberType, ModFlags);
6617 OptAttributes.Emit (ec, this);
6620 if (!IsInterface) {
6621 Add.Emit (Parent);
6622 Remove.Emit (Parent);
6625 base.Emit ();
6628 public override string GetSignatureForError ()
6630 if (EventBuilder == null)
6631 return base.GetSignatureForError (Parent);
6633 return TypeManager.GetFullNameSignature (EventBuilder);
6638 public class Indexer : PropertyBase {
6640 class GetIndexerMethod: GetMethod
6642 public GetIndexerMethod (MethodCore method):
6643 base (method)
6647 public GetIndexerMethod (MethodCore method, Accessor accessor):
6648 base (method, accessor)
6652 public override Type[] ParameterTypes {
6653 get {
6654 return method.ParameterTypes;
6659 class SetIndexerMethod: SetMethod
6661 readonly Parameters parameters;
6663 public SetIndexerMethod (MethodCore method):
6664 base (method)
6668 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
6669 base (method, accessor)
6671 this.parameters = parameters;
6674 public override Type[] ParameterTypes {
6675 get {
6676 int top = method.ParameterTypes.Length;
6677 Type [] set_pars = new Type [top + 1];
6678 method.ParameterTypes.CopyTo (set_pars, 0);
6679 set_pars [top] = method.MemberType;
6680 return set_pars;
6684 protected override InternalParameters GetParameterInfo (EmitContext ec)
6686 Parameter [] fixed_parms = parameters.FixedParameters;
6688 if (fixed_parms == null){
6689 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
6690 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6691 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6693 // Here is the problem: the `value' parameter has
6694 // to come *after* the array parameter in the declaration
6695 // like this:
6696 // X (object [] x, Type value)
6697 // .param [0]
6699 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6700 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6704 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
6706 fixed_parms.CopyTo (tmp, 0);
6707 tmp [fixed_parms.Length] = new Parameter (
6708 method.Type, "value", Parameter.Modifier.NONE, null);
6710 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
6711 Type [] types = set_formal_params.GetParameterInfo (ec);
6713 return new InternalParameters (types, set_formal_params);
6718 const int AllowedModifiers =
6719 Modifiers.NEW |
6720 Modifiers.PUBLIC |
6721 Modifiers.PROTECTED |
6722 Modifiers.INTERNAL |
6723 Modifiers.PRIVATE |
6724 Modifiers.VIRTUAL |
6725 Modifiers.SEALED |
6726 Modifiers.OVERRIDE |
6727 Modifiers.UNSAFE |
6728 Modifiers.EXTERN |
6729 Modifiers.ABSTRACT;
6731 const int AllowedInterfaceModifiers =
6732 Modifiers.NEW;
6735 public Indexer (TypeContainer ds, Expression type, MemberName name, int mod,
6736 bool is_iface, Parameters parameters, Attributes attrs,
6737 Accessor get_block, Accessor set_block, Location loc)
6738 : base (ds, type, mod,
6739 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6740 is_iface, name, parameters, attrs, loc)
6742 if (get_block == null)
6743 Get = new GetIndexerMethod (this);
6744 else
6745 Get = new GetIndexerMethod (this, get_block);
6747 if (set_block == null)
6748 Set = new SetIndexerMethod (this);
6749 else
6750 Set = new SetIndexerMethod (this, parameters, set_block);
6753 public override bool Define ()
6755 PropertyAttributes prop_attr =
6756 PropertyAttributes.RTSpecialName |
6757 PropertyAttributes.SpecialName;
6759 if (!base.Define ())
6760 return false;
6762 if (OptAttributes != null) {
6763 Attribute indexer_attr = OptAttributes.GetIndexerNameAttribute (ec);
6764 if (indexer_attr != null) {
6765 ShortName = indexer_attr.GetIndexerAttributeValue (ec);
6767 if (IsExplicitImpl) {
6768 Report.Error (415, indexer_attr.Location,
6769 "The 'IndexerName' attribute is valid only on an" +
6770 "indexer that is not an explicit interface member declaration");
6771 return false;
6774 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6775 Report.Error (609, indexer_attr.Location,
6776 "Cannot set the 'IndexerName' attribute on an indexer marked override");
6777 return false;
6780 if (!Tokenizer.IsValidIdentifier (ShortName)) {
6781 Report.Error (633, indexer_attr.Location,
6782 "The argument to the 'IndexerName' attribute must be a valid identifier");
6783 return false;
6786 UpdateMemberName ();
6790 if (InterfaceType != null) {
6791 string parent_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6792 if (parent_IndexerName != Name)
6793 ShortName = parent_IndexerName;
6794 UpdateMemberName ();
6797 if (!Parent.AddToMemberContainer (this, true) ||
6798 !Parent.AddToMemberContainer (Get, true) || !Parent.AddToMemberContainer (Set, true))
6799 return false;
6801 if (!CheckBase ())
6802 return false;
6804 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6805 if (!Get.IsDummy){
6806 GetBuilder = Get.Define (Parent);
6807 if (GetBuilder == null)
6808 return false;
6811 if (!Set.IsDummy){
6812 SetBuilder = Set.Define (Parent);
6813 if (SetBuilder == null)
6814 return false;
6818 // Now name the parameters
6820 Parameter [] p = Parameters.FixedParameters;
6821 if (p != null) {
6822 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
6823 Report.Error (631, Location, "ref and out are not valid in this context");
6824 return false;
6827 int i;
6829 for (i = 0; i < p.Length; ++i) {
6830 if (!Get.IsDummy)
6831 GetBuilder.DefineParameter (
6832 i + 1, p [i].Attributes, p [i].Name);
6834 if (!Set.IsDummy)
6835 SetBuilder.DefineParameter (
6836 i + 1, p [i].Attributes, p [i].Name);
6839 if (!Set.IsDummy)
6840 SetBuilder.DefineParameter (
6841 i + 1, ParameterAttributes.None, "value");
6843 if (i != ParameterTypes.Length) {
6844 Parameter array_param = Parameters.ArrayParameter;
6846 SetBuilder.DefineParameter (
6847 i + 1, array_param.Attributes, array_param.Name);
6851 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6852 Name, prop_attr, MemberType, ParameterTypes);
6854 if (!Get.IsDummy)
6855 PropertyBuilder.SetGetMethod (GetBuilder);
6857 if (!Set.IsDummy)
6858 PropertyBuilder.SetSetMethod (SetBuilder);
6860 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
6862 return true;
6865 public override string GetSignatureForError ()
6867 if (PropertyBuilder == null)
6868 return GetSignatureForError (Parent);
6870 return TypeManager.CSharpSignature (PropertyBuilder, true);
6873 public override string GetSignatureForError(TypeContainer tc)
6875 return String.Concat (tc.Name, ".this[", Parameters.FixedParameters [0].TypeName.ToString (), ']');
6879 public class Operator : MethodCore, IIteratorContainer {
6881 const int AllowedModifiers =
6882 Modifiers.PUBLIC |
6883 Modifiers.UNSAFE |
6884 Modifiers.EXTERN |
6885 Modifiers.STATIC;
6887 public enum OpType : byte {
6889 // Unary operators
6890 LogicalNot,
6891 OnesComplement,
6892 Increment,
6893 Decrement,
6894 True,
6895 False,
6897 // Unary and Binary operators
6898 Addition,
6899 Subtraction,
6901 UnaryPlus,
6902 UnaryNegation,
6904 // Binary operators
6905 Multiply,
6906 Division,
6907 Modulus,
6908 BitwiseAnd,
6909 BitwiseOr,
6910 ExclusiveOr,
6911 LeftShift,
6912 RightShift,
6913 Equality,
6914 Inequality,
6915 GreaterThan,
6916 LessThan,
6917 GreaterThanOrEqual,
6918 LessThanOrEqual,
6920 // Implicit and Explicit
6921 Implicit,
6922 Explicit
6925 public readonly OpType OperatorType;
6926 public MethodBuilder OperatorMethodBuilder;
6928 public Method OperatorMethod;
6930 static string[] attribute_targets = new string [] { "method", "return" };
6932 public Operator (TypeContainer parent, OpType type, Expression ret_type,
6933 int mod_flags, Parameters parameters,
6934 ToplevelBlock block, Attributes attrs, Location loc)
6935 : base (parent, ret_type, mod_flags, AllowedModifiers, false,
6936 new MemberName ("op_" + type), attrs, parameters, loc)
6938 OperatorType = type;
6939 Block = block;
6942 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6944 OperatorMethod.ApplyAttributeBuilder (a, cb);
6947 public override AttributeTargets AttributeTargets {
6948 get {
6949 return AttributeTargets.Method;
6953 protected override bool CheckForDuplications()
6955 ArrayList ar = Parent.Operators;
6956 if (ar != null) {
6957 int arLen = ar.Count;
6959 for (int i = 0; i < arLen; i++) {
6960 Operator o = (Operator) ar [i];
6961 if (IsDuplicateImplementation (o))
6962 return false;
6966 ar = Parent.Methods;
6967 if (ar != null) {
6968 int arLen = ar.Count;
6970 for (int i = 0; i < arLen; i++) {
6971 Method m = (Method) ar [i];
6972 if (IsDuplicateImplementation (m))
6973 return false;
6977 return true;
6980 public override bool Define ()
6983 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
6984 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6985 Report.Error (558, Location, "User defined operators '{0}' must be declared static and public", GetSignatureForError (Parent));
6986 return false;
6989 if (!DoDefine ())
6990 return false;
6992 OperatorMethod = new Method (
6993 Parent, Type, ModFlags, false, MemberName,
6994 Parameters, OptAttributes, Location);
6996 OperatorMethod.Block = Block;
6997 OperatorMethod.IsOperator = true;
6998 OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
6999 OperatorMethod.Define ();
7001 if (OperatorMethod.MethodBuilder == null)
7002 return false;
7004 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7006 parameter_types = OperatorMethod.ParameterTypes;
7007 Type declaring_type = OperatorMethodBuilder.DeclaringType;
7008 Type return_type = OperatorMethod.ReturnType;
7009 Type first_arg_type = parameter_types [0];
7011 if (!CheckBase ())
7012 return false;
7014 // Rules for conversion operators
7016 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7017 if (first_arg_type == return_type && first_arg_type == declaring_type){
7018 Report.Error (
7019 555, Location,
7020 "User-defined conversion cannot take an object of the " +
7021 "enclosing type and convert to an object of the enclosing" +
7022 " type");
7023 return false;
7026 if (first_arg_type != declaring_type && return_type != declaring_type){
7027 Report.Error (
7028 556, Location,
7029 "User-defined conversion must convert to or from the " +
7030 "enclosing type");
7031 return false;
7034 if (first_arg_type == TypeManager.object_type ||
7035 return_type == TypeManager.object_type){
7036 Report.Error (
7037 -8, Location,
7038 "User-defined conversion cannot convert to or from " +
7039 "object type");
7040 return false;
7043 if (first_arg_type.IsInterface || return_type.IsInterface){
7044 Report.Error (
7045 552, Location,
7046 "User-defined conversion cannot convert to or from an " +
7047 "interface type");
7048 return false;
7051 if (first_arg_type.IsSubclassOf (return_type)
7052 || return_type.IsSubclassOf (first_arg_type)){
7053 if (declaring_type.IsSubclassOf (return_type)) {
7054 Report.Error (553, Location, "'{0}' : user defined conversion to/from base class", GetSignatureForError ());
7055 return false;
7057 Report.Error (554, Location, "'{0}' : user defined conversion to/from derived class", GetSignatureForError ());
7058 return false;
7060 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7061 if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
7062 Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
7063 return false;
7065 } else if (Parameters.FixedParameters.Length == 1) {
7066 // Checks for Unary operators
7068 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7069 if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7070 Report.Error (448, Location,
7071 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7072 return false;
7074 if (first_arg_type != declaring_type) {
7075 Report.Error (
7076 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7077 return false;
7081 if (first_arg_type != declaring_type){
7082 Report.Error (
7083 562, Location,
7084 "The parameter of a unary operator must be the " +
7085 "containing type");
7086 return false;
7089 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7090 if (return_type != TypeManager.bool_type){
7091 Report.Error (
7092 215, Location,
7093 "The return type of operator True or False " +
7094 "must be bool");
7095 return false;
7099 } else {
7100 // Checks for Binary operators
7102 if (first_arg_type != declaring_type &&
7103 parameter_types [1] != declaring_type){
7104 Report.Error (
7105 563, Location,
7106 "One of the parameters of a binary operator must " +
7107 "be the containing type");
7108 return false;
7112 return true;
7115 public override void Emit ()
7118 // abstract or extern methods have no bodies
7120 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7121 return;
7123 OperatorMethod.Emit ();
7124 Block = null;
7127 // Operator cannot be override
7128 protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
7130 return null;
7133 public static string GetName (OpType ot)
7135 switch (ot){
7136 case OpType.LogicalNot:
7137 return "!";
7138 case OpType.OnesComplement:
7139 return "~";
7140 case OpType.Increment:
7141 return "++";
7142 case OpType.Decrement:
7143 return "--";
7144 case OpType.True:
7145 return "true";
7146 case OpType.False:
7147 return "false";
7148 case OpType.Addition:
7149 return "+";
7150 case OpType.Subtraction:
7151 return "-";
7152 case OpType.UnaryPlus:
7153 return "+";
7154 case OpType.UnaryNegation:
7155 return "-";
7156 case OpType.Multiply:
7157 return "*";
7158 case OpType.Division:
7159 return "/";
7160 case OpType.Modulus:
7161 return "%";
7162 case OpType.BitwiseAnd:
7163 return "&";
7164 case OpType.BitwiseOr:
7165 return "|";
7166 case OpType.ExclusiveOr:
7167 return "^";
7168 case OpType.LeftShift:
7169 return "<<";
7170 case OpType.RightShift:
7171 return ">>";
7172 case OpType.Equality:
7173 return "==";
7174 case OpType.Inequality:
7175 return "!=";
7176 case OpType.GreaterThan:
7177 return ">";
7178 case OpType.LessThan:
7179 return "<";
7180 case OpType.GreaterThanOrEqual:
7181 return ">=";
7182 case OpType.LessThanOrEqual:
7183 return "<=";
7184 case OpType.Implicit:
7185 return "implicit";
7186 case OpType.Explicit:
7187 return "explicit";
7188 default: return "";
7192 public override string GetSignatureForError (TypeContainer tc)
7194 StringBuilder sb = new StringBuilder ();
7195 sb.AppendFormat ("{0}.operator {1} {2}({3}", tc.Name, GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type),
7196 Parameters.FixedParameters [0].GetSignatureForError ());
7198 if (Parameters.FixedParameters.Length > 1) {
7199 sb.Append (",");
7200 sb.Append (Parameters.FixedParameters [1].GetSignatureForError ());
7202 sb.Append (")");
7203 return sb.ToString ();
7206 public override string GetSignatureForError ()
7208 return ToString ();
7211 public override string ToString ()
7213 if (OperatorMethod == null)
7214 return Name;
7216 Type return_type = OperatorMethod.ReturnType;
7217 Type [] param_types = OperatorMethod.ParameterTypes;
7219 if (Parameters.FixedParameters.Length == 1)
7220 return String.Format (
7221 "{0} operator {1}({2})",
7222 TypeManager.CSharpName (return_type),
7223 GetName (OperatorType),
7224 param_types [0]);
7225 else
7226 return String.Format (
7227 "{0} operator {1}({2}, {3})",
7228 TypeManager.CSharpName (return_type),
7229 GetName (OperatorType),
7230 param_types [0], param_types [1]);
7233 public override string[] ValidAttributeTargets {
7234 get {
7235 return attribute_targets;
7239 public void SetYields ()
7241 ModFlags |= Modifiers.METHOD_YIELDS;
7246 // This is used to compare method signatures
7248 struct MethodSignature {
7249 public string Name;
7250 public Type RetType;
7251 public Type [] Parameters;
7253 /// <summary>
7254 /// This delegate is used to extract methods which have the
7255 /// same signature as the argument
7256 /// </summary>
7257 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7259 public MethodSignature (string name, Type ret_type, Type [] parameters)
7261 Name = name;
7262 RetType = ret_type;
7264 if (parameters == null)
7265 Parameters = TypeManager.NoTypes;
7266 else
7267 Parameters = parameters;
7270 public override string ToString ()
7272 string pars = "";
7273 if (Parameters.Length != 0){
7274 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7275 for (int i = 0; i < Parameters.Length; i++){
7276 sb.Append (Parameters [i]);
7277 if (i+1 < Parameters.Length)
7278 sb.Append (", ");
7280 pars = sb.ToString ();
7283 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7286 public override int GetHashCode ()
7288 return Name.GetHashCode ();
7291 public override bool Equals (Object o)
7293 MethodSignature other = (MethodSignature) o;
7295 if (other.Name != Name)
7296 return false;
7298 if (other.RetType != RetType)
7299 return false;
7301 if (Parameters == null){
7302 if (other.Parameters == null)
7303 return true;
7304 return false;
7307 if (other.Parameters == null)
7308 return false;
7310 int c = Parameters.Length;
7311 if (other.Parameters.Length != c)
7312 return false;
7314 for (int i = 0; i < c; i++)
7315 if (other.Parameters [i] != Parameters [i])
7316 return false;
7318 return true;
7321 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7323 MethodSignature sig = (MethodSignature) filter_criteria;
7325 if (m.Name != sig.Name)
7326 return false;
7328 Type ReturnType;
7329 MethodInfo mi = m as MethodInfo;
7330 PropertyInfo pi = m as PropertyInfo;
7332 if (mi != null)
7333 ReturnType = mi.ReturnType;
7334 else if (pi != null)
7335 ReturnType = pi.PropertyType;
7336 else
7337 return false;
7340 // we use sig.RetType == null to mean `do not check the
7341 // method return value.
7343 if (sig.RetType != null)
7344 if (ReturnType != sig.RetType)
7345 return false;
7347 Type [] args;
7348 if (mi != null)
7349 args = TypeManager.GetArgumentTypes (mi);
7350 else
7351 args = TypeManager.GetArgumentTypes (pi);
7352 Type [] sigp = sig.Parameters;
7354 if (args.Length != sigp.Length)
7355 return false;
7357 for (int i = args.Length; i > 0; ){
7358 i--;
7359 if (args [i] != sigp [i])
7360 return false;
7362 return true;