2006-04-27 Jonathan Chambers <jonathan.chambers@ansys.com>
[mcs.git] / gmcs / class.cs
blob24645f5ef8da0993824e553e6566cbfd143d50cf
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
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)
11 // (C) 2004 Novell, Inc
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
33 #define CACHE
34 using System;
35 using System.Collections;
36 using System.Collections.Specialized;
37 using System.Reflection;
38 using System.Reflection.Emit;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Security;
42 using System.Security.Permissions;
43 using System.Text;
44 using System.Xml;
46 using Mono.CompilerServices.SymbolWriter;
48 namespace Mono.CSharp {
50 public enum Kind {
51 Root,
52 Struct,
53 Class,
54 Interface
57 /// <summary>
58 /// This is the base class for structs and classes.
59 /// </summary>
60 public abstract class TypeContainer : DeclSpace, IMemberContainer {
62 public class MemberCoreArrayList: ArrayList
64 /// <summary>
65 /// Defines the MemberCore objects that are in this array
66 /// </summary>
67 public virtual void DefineContainerMembers ()
69 foreach (MemberCore mc in this) {
70 try {
71 mc.Define ();
73 catch (Exception e) {
74 throw new InternalErrorException (mc.Location, mc.GetSignatureForError (), e);
79 public virtual void Emit ()
81 foreach (MemberCore mc in this)
82 mc.Emit ();
86 public class MethodArrayList : MemberCoreArrayList
88 [Flags]
89 enum CachedMethods {
90 Equals = 1,
91 GetHashCode = 1 << 1
94 CachedMethods cached_method;
95 TypeContainer container;
97 public MethodArrayList (TypeContainer container)
99 this.container = container;
102 /// <summary>
103 /// Method container contains Equals method
104 /// </summary>
105 public bool HasEquals {
106 set {
107 cached_method |= CachedMethods.Equals;
110 get {
111 return (cached_method & CachedMethods.Equals) != 0;
115 /// <summary>
116 /// Method container contains GetHashCode method
117 /// </summary>
118 public bool HasGetHashCode {
119 set {
120 cached_method |= CachedMethods.GetHashCode;
123 get {
124 return (cached_method & CachedMethods.GetHashCode) != 0;
128 public override void DefineContainerMembers ()
130 base.DefineContainerMembers ();
132 if (HasEquals && !HasGetHashCode) {
133 Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
139 public sealed class IndexerArrayList : MemberCoreArrayList
141 /// <summary>
142 /// The indexer name for this container
143 /// </summary>
144 public string IndexerName = DefaultIndexerName;
146 bool seen_normal_indexers = false;
148 TypeContainer container;
150 public IndexerArrayList (TypeContainer container)
152 this.container = container;
155 /// <summary>
156 /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
157 /// class is consistent. Either it is `Item' or it is the name defined by all the
158 /// indexers with the `IndexerName' attribute.
160 /// Turns out that the IndexerNameAttribute is applied to each indexer,
161 /// but it is never emitted, instead a DefaultMember attribute is attached
162 /// to the class.
163 /// </summary>
164 public override void DefineContainerMembers()
166 base.DefineContainerMembers ();
168 string class_indexer_name = null;
171 // If there's both an explicit and an implicit interface implementation, the
172 // explicit one actually implements the interface while the other one is just
173 // a normal indexer. See bug #37714.
176 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
177 foreach (Indexer i in this) {
178 if (i.InterfaceType != null) {
179 if (seen_normal_indexers)
180 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
181 continue;
184 seen_normal_indexers = true;
186 if (class_indexer_name == null) {
187 class_indexer_name = i.ShortName;
188 continue;
191 if (i.ShortName != class_indexer_name)
192 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");
195 if (class_indexer_name != null)
196 IndexerName = class_indexer_name;
199 public override void Emit ()
201 base.Emit ();
203 if (!seen_normal_indexers)
204 return;
206 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
207 container.TypeBuilder.SetCustomAttribute (cb);
211 public class OperatorArrayList: MemberCoreArrayList
213 TypeContainer container;
215 public OperatorArrayList (TypeContainer container)
217 this.container = container;
221 // Operator pair checking
223 class OperatorEntry
225 public int flags;
226 public Type ret_type;
227 public Type type1, type2;
228 public Operator op;
229 public Operator.OpType ot;
231 public OperatorEntry (int f, Operator o)
233 flags = f;
235 ret_type = o.MemberType;
236 Type [] pt = o.ParameterTypes;
237 type1 = pt [0];
238 type2 = pt [1];
239 op = o;
240 ot = o.OperatorType;
243 public override int GetHashCode ()
245 return ret_type.GetHashCode ();
248 public override bool Equals (object o)
250 OperatorEntry other = (OperatorEntry) o;
252 if (other.ret_type != ret_type)
253 return false;
254 if (other.type1 != type1)
255 return false;
256 if (other.type2 != type2)
257 return false;
258 return true;
263 // Checks that some operators come in pairs:
264 // == and !=
265 // > and <
266 // >= and <=
267 // true and false
269 // They are matched based on the return type and the argument types
271 void CheckPairedOperators ()
273 IDictionary pairs = new HybridDictionary ();
274 Operator true_op = null;
275 Operator false_op = null;
276 bool has_equality_or_inequality = false;
278 // Register all the operators we care about.
279 foreach (Operator op in this){
280 int reg = 0;
282 // Skip erroneous code.
283 if (op.MethodBuilder == null)
284 continue;
286 switch (op.OperatorType){
287 case Operator.OpType.Equality:
288 reg = 1;
289 has_equality_or_inequality = true;
290 break;
291 case Operator.OpType.Inequality:
292 reg = 2;
293 has_equality_or_inequality = true;
294 break;
296 case Operator.OpType.True:
297 true_op = op;
298 break;
299 case Operator.OpType.False:
300 false_op = op;
301 break;
303 case Operator.OpType.GreaterThan:
304 reg = 1; break;
305 case Operator.OpType.LessThan:
306 reg = 2; break;
308 case Operator.OpType.GreaterThanOrEqual:
309 reg = 1; break;
310 case Operator.OpType.LessThanOrEqual:
311 reg = 2; break;
313 if (reg == 0)
314 continue;
316 OperatorEntry oe = new OperatorEntry (reg, op);
318 object o = pairs [oe];
319 if (o == null)
320 pairs [oe] = oe;
321 else {
322 oe = (OperatorEntry) o;
323 oe.flags |= reg;
327 if (true_op != null){
328 if (false_op == null)
329 Report.Error (216, true_op.Location, "The operator `{0}' requires a matching operator `false' to also be defined",
330 true_op.GetSignatureForError ());
331 } else if (false_op != null)
332 Report.Error (216, false_op.Location, "The operator `{0}' requires a matching operator `true' to also be defined",
333 false_op.GetSignatureForError ());
336 // Look for the mistakes.
338 foreach (DictionaryEntry de in pairs){
339 OperatorEntry oe = (OperatorEntry) de.Key;
341 if (oe.flags == 3)
342 continue;
344 string s = "";
345 switch (oe.ot){
346 case Operator.OpType.Equality:
347 s = "!=";
348 break;
349 case Operator.OpType.Inequality:
350 s = "==";
351 break;
352 case Operator.OpType.GreaterThan:
353 s = "<";
354 break;
355 case Operator.OpType.LessThan:
356 s = ">";
357 break;
358 case Operator.OpType.GreaterThanOrEqual:
359 s = "<=";
360 break;
361 case Operator.OpType.LessThanOrEqual:
362 s = ">=";
363 break;
365 Report.Error (216, oe.op.Location,
366 "The operator `{0}' requires a matching operator `{1}' to also be defined",
367 oe.op.GetSignatureForError (), s);
370 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
371 if (container.Methods == null || !container.Methods.HasEquals)
372 Report.Warning (660, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
374 if (container.Methods == null || !container.Methods.HasGetHashCode)
375 Report.Warning (661, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
379 public override void DefineContainerMembers ()
381 base.DefineContainerMembers ();
382 CheckPairedOperators ();
387 // Whether this is a struct, class or interface
388 public readonly Kind Kind;
390 // Holds a list of classes and structures
391 protected ArrayList types;
393 // Holds the list of properties
394 MemberCoreArrayList properties;
396 // Holds the list of enumerations
397 MemberCoreArrayList enums;
399 // Holds the list of delegates
400 MemberCoreArrayList delegates;
402 // Holds the list of constructors
403 protected MemberCoreArrayList instance_constructors;
405 // Holds the list of fields
406 MemberCoreArrayList fields;
408 // Holds a list of fields that have initializers
409 protected ArrayList initialized_fields;
411 // Holds a list of static fields that have initializers
412 protected ArrayList initialized_static_fields;
414 // Holds the list of constants
415 MemberCoreArrayList constants;
417 // Holds the list of
418 MemberCoreArrayList interfaces;
420 // Holds the methods.
421 MethodArrayList methods;
423 // Holds the events
424 protected MemberCoreArrayList events;
426 // Holds the indexers
427 IndexerArrayList indexers;
429 // Holds the operators
430 MemberCoreArrayList operators;
432 // Holds the iterators
433 ArrayList iterators;
436 // Pointers to the default constructor and the default static constructor
438 protected Constructor default_constructor;
439 protected Constructor default_static_constructor;
442 // Points to the first non-static field added to the container.
444 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
445 // and the first one's as good as any.
447 FieldBase first_nonstatic_field = null;
450 // This one is computed after we can distinguish interfaces
451 // from classes from the arraylist `type_bases'
453 TypeExpr base_type;
454 TypeExpr[] iface_exprs;
456 ArrayList type_bases;
458 bool members_defined;
459 bool members_defined_ok;
461 // The interfaces we implement.
462 protected Type[] ifaces;
464 // The base member cache and our member cache
465 MemberCache base_cache;
466 MemberCache member_cache;
468 public const string DefaultIndexerName = "Item";
470 Type GenericType;
471 GenericTypeParameterBuilder[] gen_params;
473 public TypeContainer PartialContainer;
474 ArrayList partial_parts;
476 /// <remarks>
477 /// The pending methods that need to be implemented
478 // (interfaces or abstract methods)
479 /// </remarks>
480 PendingImplementation pending;
482 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
483 Attributes attrs, Kind kind)
484 : base (ns, parent, name, attrs)
486 if (parent != null && parent != RootContext.Tree.Types && parent.NamespaceEntry != ns)
487 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
489 this.Kind = kind;
490 this.PartialContainer = this;
493 public bool AddToMemberContainer (MemberCore symbol)
495 return AddToContainer (symbol, symbol.MemberName.MethodName);
498 protected virtual bool AddToTypeContainer (DeclSpace ds)
500 return AddToContainer (ds, ds.Basename);
503 public void AddConstant (Const constant)
505 if (!AddToMemberContainer (constant))
506 return;
508 if (constants == null)
509 constants = new MemberCoreArrayList ();
511 constants.Add (constant);
514 public void AddEnum (Mono.CSharp.Enum e)
516 if (!AddToTypeContainer (e))
517 return;
519 if (enums == null)
520 enums = new MemberCoreArrayList ();
522 enums.Add (e);
525 public bool AddClassOrStruct (TypeContainer c)
527 if (!AddToTypeContainer (c))
528 return false;
530 if (types == null)
531 types = new ArrayList (2);
533 RootContext.Tree.RecordDecl (c.NamespaceEntry.NS, c.MemberName, c);
534 types.Add (c);
535 return true;
538 public virtual TypeContainer AddPartial (TypeContainer nextPart)
540 return AddPartial (nextPart, nextPart.Basename);
543 protected TypeContainer AddPartial (TypeContainer nextPart, string name)
545 nextPart.ModFlags |= Modifiers.PARTIAL;
546 TypeContainer tc = defined_names [name] as TypeContainer;
548 if (tc == null) {
549 if (nextPart is Interface)
550 AddInterface (nextPart);
551 else
552 AddClassOrStruct (nextPart);
553 return nextPart;
556 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
557 Report.SymbolRelatedToPreviousError (tc);
558 Error_MissingPartialModifier (nextPart);
559 return tc;
562 if (tc.Kind != nextPart.Kind) {
563 Report.SymbolRelatedToPreviousError (tc);
564 Report.Error (261, nextPart.Location,
565 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
566 nextPart.GetSignatureForError ());
567 return tc;
570 if ((tc.ModFlags & Modifiers.Accessibility) != (nextPart.ModFlags & Modifiers.Accessibility) &&
571 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
572 (nextPart.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
573 Report.SymbolRelatedToPreviousError (tc);
574 Report.Error (262, nextPart.Location,
575 "Partial declarations of `{0}' have conflicting accessibility modifiers",
576 nextPart.GetSignatureForError ());
577 return tc;
580 if (tc.partial_parts == null)
581 tc.partial_parts = new ArrayList (1);
583 tc.ModFlags |= nextPart.ModFlags;
584 if (nextPart.attributes != null) {
585 if (tc.attributes == null)
586 tc.attributes = nextPart.attributes;
587 else
588 tc.attributes.AddAttributes (nextPart.attributes.Attrs);
591 nextPart.PartialContainer = tc;
592 tc.partial_parts.Add (nextPart);
593 return tc;
596 public void AddDelegate (Delegate d)
598 if (!AddToTypeContainer (d))
599 return;
601 if (delegates == null)
602 delegates = new MemberCoreArrayList ();
604 delegates.Add (d);
607 public void AddMethod (Method method)
609 if (!AddToMemberContainer (method))
610 return;
612 if (methods == null)
613 methods = new MethodArrayList (this);
615 if (method.MemberName.Left != null)
616 methods.Insert (0, method);
617 else
618 methods.Add (method);
622 // Do not use this method: use AddMethod.
624 // This is only used by iterators.
626 public void AppendMethod (Method method)
628 if (!AddToMemberContainer (method))
629 return;
631 if (methods == null)
632 methods = new MethodArrayList (this);
634 methods.Add (method);
637 public void AddConstructor (Constructor c)
639 if (c.Name != MemberName.Name) {
640 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
643 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
645 if (is_static){
646 if (default_static_constructor != null) {
647 Report.SymbolRelatedToPreviousError (default_static_constructor);
648 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
649 return;
652 default_static_constructor = c;
653 } else {
654 if (c.Parameters.Empty){
655 if (default_constructor != null) {
656 Report.SymbolRelatedToPreviousError (default_constructor);
657 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
658 return;
660 default_constructor = c;
663 if (instance_constructors == null)
664 instance_constructors = new MemberCoreArrayList ();
666 instance_constructors.Add (c);
670 internal static string Error111 {
671 get {
672 return "`{0}' is already defined. Rename this member or use different parameter types";
676 public bool AddInterface (TypeContainer iface)
678 if (!AddToTypeContainer (iface))
679 return false;
681 if (interfaces == null) {
682 interfaces = new MemberCoreArrayList ();
685 RootContext.Tree.RecordDecl (iface.NamespaceEntry.NS, iface.MemberName, iface);
686 interfaces.Add (iface);
687 return true;
690 public void AddField (FieldMember field)
692 if (!AddToMemberContainer (field))
693 return;
695 if (fields == null)
696 fields = new MemberCoreArrayList ();
698 fields.Add (field);
700 if ((field.ModFlags & Modifiers.STATIC) != 0)
701 return;
703 if (first_nonstatic_field == null) {
704 first_nonstatic_field = field;
705 return;
708 if (Kind == Kind.Struct &&
709 first_nonstatic_field.Parent != field.Parent &&
710 RootContext.WarningLevel >= 3) {
711 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
712 Report.Warning (282, 3, field.Location,
713 "struct instance field `{0}' found in different declaration from instance field `{1}'",
714 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
718 public void AddProperty (Property prop)
720 if (!AddToMemberContainer (prop) ||
721 !AddToMemberContainer (prop.Get) || !AddToMemberContainer (prop.Set))
722 return;
724 if (properties == null)
725 properties = new MemberCoreArrayList ();
727 if (prop.MemberName.Left != null)
728 properties.Insert (0, prop);
729 else
730 properties.Add (prop);
733 public void AddEvent (Event e)
735 if (!AddToMemberContainer (e))
736 return;
738 if (e is EventProperty) {
739 if (!AddToMemberContainer (e.Add))
740 return;
742 if (!AddToMemberContainer (e.Remove))
743 return;
746 if (events == null)
747 events = new MemberCoreArrayList ();
749 events.Add (e);
752 /// <summary>
753 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
754 /// </summary>
755 public void AddIndexer (Indexer i)
757 if (indexers == null)
758 indexers = new IndexerArrayList (this);
760 if (i.IsExplicitImpl)
761 indexers.Insert (0, i);
762 else
763 indexers.Add (i);
766 public void AddOperator (Operator op)
768 if (!AddToMemberContainer (op))
769 return;
771 if (operators == null)
772 operators = new OperatorArrayList (this);
774 operators.Add (op);
777 public void AddIterator (Iterator i)
779 if (iterators == null)
780 iterators = new ArrayList ();
782 iterators.Add (i);
785 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
787 if (a.Type == TypeManager.default_member_type) {
788 if (Indexers != null) {
789 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
790 return;
794 base.ApplyAttributeBuilder (a, cb);
797 public override AttributeTargets AttributeTargets {
798 get {
799 throw new NotSupportedException ();
803 public ArrayList Types {
804 get {
805 return types;
809 public MethodArrayList Methods {
810 get {
811 return methods;
815 public ArrayList Constants {
816 get {
817 return constants;
821 public ArrayList Interfaces {
822 get {
823 return interfaces;
827 public ArrayList Iterators {
828 get {
829 return iterators;
833 protected Type BaseType {
834 get {
835 return TypeBuilder.BaseType;
839 public ArrayList Bases {
840 get {
841 return type_bases;
844 set {
845 type_bases = value;
849 public ArrayList Fields {
850 get {
851 return fields;
855 public ArrayList InstanceConstructors {
856 get {
857 return instance_constructors;
861 public ArrayList Properties {
862 get {
863 return properties;
867 public ArrayList Events {
868 get {
869 return events;
873 public ArrayList Enums {
874 get {
875 return enums;
879 public ArrayList Indexers {
880 get {
881 return indexers;
885 public ArrayList Operators {
886 get {
887 return operators;
891 public ArrayList Delegates {
892 get {
893 return delegates;
897 protected override TypeAttributes TypeAttr {
898 get {
899 return Modifiers.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
903 public string IndexerName {
904 get {
905 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
909 public bool IsComImport {
910 get {
911 if (OptAttributes == null)
912 return false;
914 return OptAttributes.Contains (TypeManager.comimport_attr_type);
918 public virtual void RegisterFieldForInitialization (FieldBase field)
920 if ((field.ModFlags & Modifiers.STATIC) != 0){
921 if (initialized_static_fields == null)
922 initialized_static_fields = new ArrayList (4);
924 initialized_static_fields.Add (field);
925 } else {
926 if (initialized_fields == null)
927 initialized_fields = new ArrayList (4);
929 initialized_fields.Add (field);
934 // Emits the instance field initializers
936 public bool EmitFieldInitializers (EmitContext ec)
938 ArrayList fields;
940 if (ec.IsStatic){
941 fields = initialized_static_fields;
942 } else {
943 fields = initialized_fields;
946 if (fields == null)
947 return true;
949 foreach (FieldBase f in fields) {
950 f.EmitInitializer (ec);
952 return true;
955 public override string DocComment {
956 get {
957 return comment;
959 set {
960 if (value == null)
961 return;
963 comment += value;
967 public PendingImplementation PendingImplementations {
968 get { return pending; }
971 public override bool GetClsCompliantAttributeValue ()
973 if (PartialContainer != this)
974 return PartialContainer.GetClsCompliantAttributeValue ();
976 return base.GetClsCompliantAttributeValue ();
979 TypeExpr[] GetNormalBases (out TypeExpr base_class)
981 base_class = null;
982 if (Bases == null)
983 return null;
985 int count = Bases.Count;
986 int start = 0, i, j;
988 if (Kind == Kind.Class){
989 TypeExpr name = ((Expression) Bases [0]).ResolveAsBaseTerminal (this, false);
991 if (name == null){
992 return null;
995 if (!name.IsInterface) {
996 // base_class could be a class, struct, enum, delegate.
997 // This is validated in GetClassBases.
998 base_class = name;
999 start = 1;
1003 TypeExpr [] ifaces = new TypeExpr [count-start];
1005 for (i = start, j = 0; i < count; i++, j++){
1006 TypeExpr resolved = ((Expression) Bases [i]).ResolveAsTypeTerminal (this, false);
1007 if (resolved == null) {
1008 return null;
1011 ifaces [j] = resolved;
1014 return ifaces.Length == 0 ? null : ifaces;
1018 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
1020 ArrayList ifaces = new ArrayList (0);
1021 if (iface_exprs != null)
1022 ifaces.AddRange (iface_exprs);
1024 foreach (TypeContainer part in partial_parts) {
1025 TypeExpr new_base_class;
1026 TypeExpr[] new_ifaces = part.GetClassBases (out new_base_class);
1027 if (new_base_class != TypeManager.system_object_expr) {
1028 if (base_class == TypeManager.system_object_expr)
1029 base_class = new_base_class;
1030 else {
1031 if (new_base_class != null && !new_base_class.Equals (base_class)) {
1032 Report.SymbolRelatedToPreviousError (base_class.Location, "");
1033 Report.Error (263, part.Location,
1034 "Partial declarations of `{0}' must not specify different base classes",
1035 part.GetSignatureForError ());
1037 return null;
1042 if (new_ifaces == null)
1043 continue;
1045 foreach (TypeExpr iface in new_ifaces) {
1046 if (ifaces.Contains (iface))
1047 continue;
1049 ifaces.Add (iface);
1053 if (ifaces.Count == 0)
1054 return null;
1056 return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
1059 /// <summary>
1060 /// This function computes the Base class and also the
1061 /// list of interfaces that the class or struct @c implements.
1062 ///
1063 /// The return value is an array (might be null) of
1064 /// interfaces implemented (as Types).
1065 ///
1066 /// The @base_class argument is set to the base object or null
1067 /// if this is `System.Object'.
1068 /// </summary>
1069 public virtual TypeExpr [] GetClassBases (out TypeExpr base_class)
1071 TypeExpr[] ifaces = GetNormalBases (out base_class);
1073 if (ifaces == null)
1074 return null;
1076 int count = ifaces.Length;
1078 for (int i = 0; i < count; i++) {
1079 TypeExpr iface = (TypeExpr) ifaces [i];
1081 if (!iface.IsInterface) {
1082 if (Kind != Kind.Class) {
1083 // TODO: location of symbol related ....
1084 Error_TypeInListIsNotInterface (Location, iface.FullName);
1086 else if (base_class != null)
1087 Report.Error (1721, Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1088 GetSignatureForError (), base_class.GetSignatureForError (), iface.GetSignatureForError ());
1089 else {
1090 Report.Error (1722, Location, "`{0}': Base class `{1}' must be specified as first",
1091 GetSignatureForError (), iface.GetSignatureForError ());
1093 return null;
1096 for (int x = 0; x < i; x++) {
1097 if (iface.Equals (ifaces [x])) {
1098 Report.Error (528, Location,
1099 "`{0}' is already listed in " +
1100 "interface list", iface.GetSignatureForError ());
1101 return null;
1105 if ((Kind == Kind.Interface) &&
1106 !iface.AsAccessible (Parent, ModFlags)) {
1107 Report.Error (61, Location,
1108 "Inconsistent accessibility: base " +
1109 "interface `{0}' is less accessible " +
1110 "than interface `{1}'", iface.Name,
1111 Name);
1112 return null;
1115 return ifaces;
1118 bool CheckGenericInterfaces (Type[] ifaces)
1120 ArrayList already_checked = new ArrayList ();
1122 for (int i = 0; i < ifaces.Length; i++) {
1123 Type iface = ifaces [i];
1124 foreach (Type t in already_checked) {
1125 if (iface == t)
1126 continue;
1128 Type[] infered = new Type [CountTypeParameters];
1129 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, infered, null))
1130 continue;
1132 Report.Error (695, Location,
1133 "`{0}' cannot implement both `{1}' and `{2}' " +
1134 "because they may unify for some type parameter substitutions",
1135 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
1136 TypeManager.CSharpName (t));
1137 return false;
1140 already_checked.Add (iface);
1143 return true;
1146 bool error = false;
1148 protected void Error_TypeInListIsNotInterface (Location loc, string type)
1150 Report.Error (527, loc, "Type `{0}' in interface list is not an interface", type);
1153 bool DefineTypeBuilder ()
1155 try {
1156 if (IsTopLevel){
1157 if (TypeManager.NamespaceClash (Name, Location)) {
1158 return false;
1161 ModuleBuilder builder = CodeGen.Module.Builder;
1162 Type default_parent = null;
1163 if (Kind == Kind.Struct)
1164 default_parent = TypeManager.value_type;
1165 TypeBuilder = builder.DefineType (
1166 Name, TypeAttr, default_parent, null);
1167 } else {
1168 TypeBuilder builder = Parent.TypeBuilder;
1170 TypeBuilder = builder.DefineNestedType (
1171 Basename, TypeAttr, null, null);
1173 } catch (ArgumentException) {
1174 Report.RuntimeMissingSupport (Location, "static classes");
1175 return false;
1178 TypeManager.AddUserType (this);
1180 if (IsGeneric) {
1181 string[] param_names = new string [TypeParameters.Length];
1182 for (int i = 0; i < TypeParameters.Length; i++)
1183 param_names [i] = TypeParameters [i].Name;
1185 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1187 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1188 for (int i = offset; i < gen_params.Length; i++)
1189 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1192 iface_exprs = GetClassBases (out base_type);
1193 if (partial_parts != null) {
1194 iface_exprs = GetNormalPartialBases (ref base_type);
1198 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1199 // which in turn should have called DefineType()s on base types if necessary.
1201 // None of the code below should trigger DefineType()s on classes that we depend on.
1202 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1204 // Let's do it as soon as possible, since code below can call DefineType() on classes
1205 // that depend on us to be populated before they are.
1207 if (!(this is Iterator))
1208 RootContext.RegisterOrder (this);
1210 if (base_type != null) {
1211 if (IsGeneric && TypeManager.IsAttributeType (base_type.Type)) {
1212 Report.Error (698, base_type.Location,
1213 "A generic type cannot derive from `{0}' " +
1214 "because it is an attribute class",
1215 base_type.Name);
1216 return false;
1219 TypeBuilder.SetParent (base_type.Type);
1221 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1222 if (obsolete_attr != null && !IsInObsoleteScope) {
1223 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location);
1227 if (!CheckRecursiveDefinition (this)) {
1228 return false;
1231 // add interfaces that were not added at type creation
1232 if (iface_exprs != null) {
1233 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1234 if (ifaces == null) {
1235 return false;
1238 foreach (Type itype in ifaces)
1239 TypeBuilder.AddInterfaceImplementation (itype);
1241 if (!CheckGenericInterfaces (ifaces)) {
1242 return false;
1245 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1248 if (this is Iterator && !ResolveType ()) {
1249 return false;
1252 return true;
1256 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1258 public override TypeBuilder DefineType ()
1260 if (TypeBuilder != null)
1261 return TypeBuilder;
1263 if (error)
1264 return null;
1266 if (!DefineTypeBuilder ()) {
1267 error = true;
1268 return null;
1271 if (partial_parts != null) {
1272 foreach (TypeContainer part in partial_parts)
1273 part.TypeBuilder = TypeBuilder;
1276 DefineNestedTypes ();
1278 return TypeBuilder;
1281 Constraints [] constraints;
1282 public override void SetParameterInfo (ArrayList constraints_list)
1284 if (PartialContainer == this) {
1285 base.SetParameterInfo (constraints_list);
1286 return;
1289 if (constraints_list == null)
1290 return;
1292 constraints = new Constraints [PartialContainer.CountCurrentTypeParameters];
1294 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
1295 for (int i = 0; i < constraints.Length; i++) {
1296 foreach (Constraints constraint in constraints_list) {
1297 if (constraint.TypeParameter == current_params [i].Name) {
1298 constraints [i] = constraint;
1299 break;
1305 bool UpdateTypeParameterConstraints ()
1307 bool ok = true;
1308 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
1310 if (constraints == null)
1311 return true;
1313 for (int i = 0; i < current_params.Length; i++) {
1314 if (!current_params [i].UpdateConstraints (this, constraints [i])) {
1315 Report.Error (265, Location, "Partial declarations of `{0}' have " +
1316 "inconsistent constraints for type parameter `{1}'.",
1317 MemberName.GetTypeName (), current_params [i].Name);
1318 ok = false;
1322 return ok;
1325 public bool ResolveType ()
1327 if ((base_type != null) &&
1328 (base_type.ResolveAsTypeTerminal (this, false) == null)) {
1329 error = true;
1330 return false;
1333 if (!IsGeneric)
1334 return true;
1336 if (PartialContainer != this)
1337 throw new InternalErrorException ();
1339 TypeExpr current_type = null;
1341 foreach (TypeParameter type_param in CurrentTypeParameters) {
1342 if (!type_param.Resolve (this)) {
1343 error = true;
1344 return false;
1348 if (partial_parts != null) {
1349 foreach (TypeContainer part in partial_parts) {
1350 if (!part.UpdateTypeParameterConstraints ()) {
1351 error = true;
1352 return false;
1357 foreach (TypeParameter type_param in TypeParameters) {
1358 if (!type_param.DefineType (this)) {
1359 error = true;
1360 return false;
1364 current_type = new ConstructedType (TypeBuilder, TypeParameters, Location);
1366 foreach (TypeParameter type_param in TypeParameters)
1367 if (!type_param.CheckDependencies ()) {
1368 error = true;
1369 return false;
1372 if (current_type != null) {
1373 current_type = current_type.ResolveAsTypeTerminal (this, false);
1374 if (current_type == null) {
1375 error = true;
1376 return false;
1379 CurrentType = current_type.Type;
1382 return true;
1385 protected virtual bool DefineNestedTypes ()
1387 if (Interfaces != null) {
1388 foreach (TypeContainer iface in Interfaces)
1389 if (iface.DefineType () == null)
1390 return false;
1393 if (Types != null) {
1394 foreach (TypeContainer tc in Types)
1395 if (tc.DefineType () == null)
1396 return false;
1399 if (Delegates != null) {
1400 foreach (Delegate d in Delegates)
1401 if (d.DefineType () == null)
1402 return false;
1405 if (Enums != null) {
1406 foreach (Enum en in Enums)
1407 if (en.DefineType () == null)
1408 return false;
1411 return true;
1414 TypeContainer InTransit;
1416 protected bool CheckRecursiveDefinition (TypeContainer tc)
1418 if (InTransit != null) {
1419 Report.SymbolRelatedToPreviousError (this);
1420 if (this is Interface)
1421 Report.Error (
1422 529, tc.Location, "Inherited interface `{0}' causes a " +
1423 "cycle in the interface hierarchy of `{1}'",
1424 GetSignatureForError (), tc.GetSignatureForError ());
1425 else
1426 Report.Error (
1427 146, tc.Location, "Circular base class dependency " +
1428 "involving `{0}' and `{1}'",
1429 tc.GetSignatureForError (), GetSignatureForError ());
1430 return false;
1433 InTransit = tc;
1435 if (BaseType != null) {
1436 Type t = TypeManager.DropGenericTypeArguments (BaseType);
1437 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1438 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1439 return false;
1442 if (iface_exprs != null) {
1443 foreach (TypeExpr iface in iface_exprs) {
1444 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1445 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1446 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1447 return false;
1451 InTransit = null;
1452 return true;
1455 public static void Error_KeywordNotAllowed (Location loc)
1457 Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
1460 /// <summary>
1461 /// Populates our TypeBuilder with fields and methods
1462 /// </summary>
1463 public override bool DefineMembers ()
1465 if (members_defined)
1466 return members_defined_ok;
1468 if (!base.DefineMembers ())
1469 return false;
1471 members_defined_ok = DoDefineMembers ();
1472 members_defined = true;
1474 return members_defined_ok;
1477 protected virtual bool DoDefineMembers ()
1479 if (iface_exprs != null) {
1480 foreach (TypeExpr iface in iface_exprs) {
1481 ConstructedType ct = iface as ConstructedType;
1482 if ((ct != null) && !ct.CheckConstraints (this))
1483 return false;
1487 if (base_type != null) {
1488 ConstructedType ct = base_type as ConstructedType;
1489 if ((ct != null) && !ct.CheckConstraints (this))
1490 return false;
1493 if (!IsTopLevel) {
1494 MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
1495 if (conflict_symbol == null) {
1496 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1497 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1498 } else {
1499 if ((ModFlags & Modifiers.NEW) == 0) {
1500 Report.SymbolRelatedToPreviousError (conflict_symbol);
1501 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1502 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1507 DefineContainerMembers (constants);
1508 DefineContainerMembers (fields);
1510 if (Kind == Kind.Struct || Kind == Kind.Class) {
1511 pending = PendingImplementation.GetPendingImplementations (this);
1515 // Constructors are not in the defined_names array
1517 DefineContainerMembers (instance_constructors);
1519 DefineContainerMembers (properties);
1520 DefineContainerMembers (events);
1521 DefineContainerMembers (indexers);
1522 DefineContainerMembers (methods);
1523 DefineContainerMembers (operators);
1524 DefineContainerMembers (enums);
1525 DefineContainerMembers (delegates);
1527 if (CurrentType != null) {
1528 GenericType = CurrentType;
1532 #if CACHE
1533 member_cache = new MemberCache (this);
1534 if (partial_parts != null) {
1535 foreach (TypeContainer part in partial_parts)
1536 part.member_cache = member_cache;
1538 #endif
1539 if (iterators != null) {
1540 foreach (Iterator iterator in iterators) {
1541 if (iterator.DefineType () == null)
1542 return false;
1545 foreach (Iterator iterator in iterators) {
1546 if (!iterator.DefineMembers ())
1547 return false;
1551 return true;
1554 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1556 if (mcal != null)
1557 mcal.DefineContainerMembers ();
1560 public override bool Define ()
1562 if (iterators != null) {
1563 foreach (Iterator iterator in iterators) {
1564 if (!iterator.Define ())
1565 return false;
1569 return true;
1572 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1574 return BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1577 /// <summary>
1578 /// This function is based by a delegate to the FindMembers routine
1579 /// </summary>
1580 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1582 return true;
1585 /// <summary>
1586 /// This filter is used by FindMembers, and we just keep
1587 /// a global for the filter to `AlwaysAccept'
1588 /// </summary>
1589 static MemberFilter accepting_filter;
1592 static TypeContainer ()
1594 accepting_filter = new MemberFilter (AlwaysAccept);
1597 public MethodInfo[] GetMethods ()
1599 ArrayList members = new ArrayList ();
1601 DefineMembers ();
1603 if (methods != null) {
1604 int len = methods.Count;
1605 for (int i = 0; i < len; i++) {
1606 Method m = (Method) methods [i];
1608 members.Add (m.MethodBuilder);
1612 if (operators != null) {
1613 int len = operators.Count;
1614 for (int i = 0; i < len; i++) {
1615 Operator o = (Operator) operators [i];
1617 members.Add (o.MethodBuilder);
1621 if (properties != null) {
1622 int len = properties.Count;
1623 for (int i = 0; i < len; i++) {
1624 Property p = (Property) properties [i];
1626 if (p.GetBuilder != null)
1627 members.Add (p.GetBuilder);
1628 if (p.SetBuilder != null)
1629 members.Add (p.SetBuilder);
1633 if (indexers != null) {
1634 int len = indexers.Count;
1635 for (int i = 0; i < len; i++) {
1636 Indexer ix = (Indexer) indexers [i];
1638 if (ix.GetBuilder != null)
1639 members.Add (ix.GetBuilder);
1640 if (ix.SetBuilder != null)
1641 members.Add (ix.SetBuilder);
1645 if (events != null) {
1646 int len = events.Count;
1647 for (int i = 0; i < len; i++) {
1648 Event e = (Event) events [i];
1650 if (e.AddBuilder != null)
1651 members.Add (e.AddBuilder);
1652 if (e.RemoveBuilder != null)
1653 members.Add (e.RemoveBuilder);
1657 MethodInfo[] retMethods = new MethodInfo [members.Count];
1658 members.CopyTo (retMethods, 0);
1659 return retMethods;
1662 // Indicated whether container has StructLayout attribute set Explicit
1663 public bool HasExplicitLayout {
1664 get {
1665 return (caching_flags & Flags.HasExplicitLayout) != 0;
1667 set {
1668 caching_flags |= Flags.HasExplicitLayout;
1672 public override Type FindNestedType (string name)
1674 if (PartialContainer != this)
1675 return PartialContainer.FindNestedType (name);
1677 ArrayList [] lists = { types, enums, delegates, interfaces };
1679 for (int j = 0; j < lists.Length; ++j) {
1680 ArrayList list = lists [j];
1681 if (list == null)
1682 continue;
1684 int len = list.Count;
1685 for (int i = 0; i < len; ++i) {
1686 DeclSpace ds = (DeclSpace) list [i];
1687 if (ds.Basename == name) {
1688 return ds.DefineType ();
1693 return null;
1696 private void FindMembers_NestedTypes (int modflags,
1697 BindingFlags bf, MemberFilter filter, object criteria,
1698 ref ArrayList members)
1700 ArrayList [] lists = { types, enums, delegates, interfaces };
1702 for (int j = 0; j < lists.Length; ++j) {
1703 ArrayList list = lists [j];
1704 if (list == null)
1705 continue;
1707 int len = list.Count;
1708 for (int i = 0; i < len; i++) {
1709 DeclSpace ds = (DeclSpace) list [i];
1711 if ((ds.ModFlags & modflags) == 0)
1712 continue;
1714 TypeBuilder tb = ds.TypeBuilder;
1715 if (tb == null) {
1716 if (!(criteria is string) || ds.Basename.Equals (criteria))
1717 tb = ds.DefineType ();
1720 if (tb != null && (filter (tb, criteria) == true)) {
1721 if (members == null)
1722 members = new ArrayList ();
1724 members.Add (tb);
1730 /// <summary>
1731 /// This method returns the members of this type just like Type.FindMembers would
1732 /// Only, we need to use this for types which are _being_ defined because MS'
1733 /// implementation can't take care of that.
1734 /// </summary>
1736 // FIXME: return an empty static array instead of null, that cleans up
1737 // some code and is consistent with some coding conventions I just found
1738 // out existed ;-)
1741 // Notice that in various cases we check if our field is non-null,
1742 // something that would normally mean that there was a bug elsewhere.
1744 // The problem happens while we are defining p-invoke methods, as those
1745 // will trigger a FindMembers, but this happens before things are defined
1747 // Since the whole process is a no-op, it is fine to check for null here.
1749 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1750 MemberFilter filter, object criteria)
1752 ArrayList members = null;
1754 int modflags = 0;
1755 if ((bf & BindingFlags.Public) != 0)
1756 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1757 Modifiers.INTERNAL;
1758 if ((bf & BindingFlags.NonPublic) != 0)
1759 modflags |= Modifiers.PRIVATE;
1761 int static_mask = 0, static_flags = 0;
1762 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1763 case BindingFlags.Static:
1764 static_mask = static_flags = Modifiers.STATIC;
1765 break;
1767 case BindingFlags.Instance:
1768 static_mask = Modifiers.STATIC;
1769 static_flags = 0;
1770 break;
1772 default:
1773 static_mask = static_flags = 0;
1774 break;
1777 Timer.StartTimer (TimerType.TcFindMembers);
1779 if (filter == null)
1780 filter = accepting_filter;
1782 if ((mt & MemberTypes.Field) != 0) {
1783 if (fields != null) {
1784 int len = fields.Count;
1785 for (int i = 0; i < len; i++) {
1786 FieldMember f = (FieldMember) fields [i];
1788 if ((f.ModFlags & modflags) == 0)
1789 continue;
1790 if ((f.ModFlags & static_mask) != static_flags)
1791 continue;
1793 FieldBuilder fb = f.FieldBuilder;
1794 if (fb != null && filter (fb, criteria) == true) {
1795 if (members == null)
1796 members = new ArrayList ();
1798 members.Add (fb);
1803 if (constants != null) {
1804 int len = constants.Count;
1805 for (int i = 0; i < len; i++) {
1806 Const con = (Const) constants [i];
1808 if ((con.ModFlags & modflags) == 0)
1809 continue;
1810 if ((con.ModFlags & static_mask) != static_flags)
1811 continue;
1813 FieldBuilder fb = con.FieldBuilder;
1814 if (fb == null) {
1815 if (con.Define ())
1816 fb = con.FieldBuilder;
1818 if (fb != null && filter (fb, criteria) == true) {
1819 if (members == null)
1820 members = new ArrayList ();
1822 members.Add (fb);
1828 if ((mt & MemberTypes.Method) != 0) {
1829 if (methods != null) {
1830 int len = methods.Count;
1831 for (int i = 0; i < len; i++) {
1832 Method m = (Method) methods [i];
1834 if ((m.ModFlags & modflags) == 0)
1835 continue;
1836 if ((m.ModFlags & static_mask) != static_flags)
1837 continue;
1839 MethodBuilder mb = m.MethodBuilder;
1841 if (mb != null && filter (mb, criteria) == true) {
1842 if (members == null)
1843 members = new ArrayList ();
1845 members.Add (mb);
1850 if (operators != null) {
1851 int len = operators.Count;
1852 for (int i = 0; i < len; i++) {
1853 Operator o = (Operator) operators [i];
1855 if ((o.ModFlags & modflags) == 0)
1856 continue;
1857 if ((o.ModFlags & static_mask) != static_flags)
1858 continue;
1860 MethodBuilder ob = o.MethodBuilder;
1861 if (ob != null && filter (ob, criteria) == true) {
1862 if (members == null)
1863 members = new ArrayList ();
1865 members.Add (ob);
1870 if (properties != null) {
1871 int len = properties.Count;
1872 for (int i = 0; i < len; i++) {
1873 Property p = (Property) properties [i];
1875 if ((p.ModFlags & modflags) == 0)
1876 continue;
1877 if ((p.ModFlags & static_mask) != static_flags)
1878 continue;
1880 MethodBuilder b;
1882 b = p.GetBuilder;
1883 if (b != null && filter (b, criteria) == true) {
1884 if (members == null)
1885 members = new ArrayList ();
1887 members.Add (b);
1890 b = p.SetBuilder;
1891 if (b != null && filter (b, criteria) == true) {
1892 if (members == null)
1893 members = new ArrayList ();
1895 members.Add (b);
1900 if (indexers != null) {
1901 int len = indexers.Count;
1902 for (int i = 0; i < len; i++) {
1903 Indexer ix = (Indexer) indexers [i];
1905 if ((ix.ModFlags & modflags) == 0)
1906 continue;
1907 if ((ix.ModFlags & static_mask) != static_flags)
1908 continue;
1910 MethodBuilder b;
1912 b = ix.GetBuilder;
1913 if (b != null && filter (b, criteria) == true) {
1914 if (members == null)
1915 members = new ArrayList ();
1917 members.Add (b);
1920 b = ix.SetBuilder;
1921 if (b != null && filter (b, criteria) == true) {
1922 if (members == null)
1923 members = new ArrayList ();
1925 members.Add (b);
1931 if ((mt & MemberTypes.Event) != 0) {
1932 if (events != null) {
1933 int len = events.Count;
1934 for (int i = 0; i < len; i++) {
1935 Event e = (Event) events [i];
1937 if ((e.ModFlags & modflags) == 0)
1938 continue;
1939 if ((e.ModFlags & static_mask) != static_flags)
1940 continue;
1942 MemberInfo eb = e.EventBuilder;
1943 if (eb != null && filter (eb, criteria) == true) {
1944 if (members == null)
1945 members = new ArrayList ();
1947 members.Add (e.EventBuilder);
1953 if ((mt & MemberTypes.Property) != 0){
1954 if (properties != null) {
1955 int len = properties.Count;
1956 for (int i = 0; i < len; i++) {
1957 Property p = (Property) properties [i];
1959 if ((p.ModFlags & modflags) == 0)
1960 continue;
1961 if ((p.ModFlags & static_mask) != static_flags)
1962 continue;
1964 MemberInfo pb = p.PropertyBuilder;
1965 if (pb != null && filter (pb, criteria) == true) {
1966 if (members == null)
1967 members = new ArrayList ();
1969 members.Add (p.PropertyBuilder);
1974 if (indexers != null) {
1975 int len = indexers.Count;
1976 for (int i = 0; i < len; i++) {
1977 Indexer ix = (Indexer) indexers [i];
1979 if ((ix.ModFlags & modflags) == 0)
1980 continue;
1981 if ((ix.ModFlags & static_mask) != static_flags)
1982 continue;
1984 MemberInfo ib = ix.PropertyBuilder;
1985 if (ib != null && filter (ib, criteria) == true) {
1986 if (members == null)
1987 members = new ArrayList ();
1989 members.Add (ix.PropertyBuilder);
1995 if ((mt & MemberTypes.NestedType) != 0)
1996 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1998 if ((mt & MemberTypes.Constructor) != 0){
1999 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
2000 int len = instance_constructors.Count;
2001 for (int i = 0; i < len; i++) {
2002 Constructor c = (Constructor) instance_constructors [i];
2004 ConstructorBuilder cb = c.ConstructorBuilder;
2005 if (cb != null && filter (cb, criteria) == true) {
2006 if (members == null)
2007 members = new ArrayList ();
2009 members.Add (cb);
2014 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2015 ConstructorBuilder cb =
2016 default_static_constructor.ConstructorBuilder;
2018 if (cb != null && filter (cb, criteria) == true) {
2019 if (members == null)
2020 members = new ArrayList ();
2022 members.Add (cb);
2028 // Lookup members in base if requested.
2030 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2031 if (TypeBuilder.BaseType != null) {
2032 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2033 if (list.Count > 0) {
2034 if (members == null)
2035 members = new ArrayList ();
2037 members.AddRange (list);
2043 Timer.StopTimer (TimerType.TcFindMembers);
2045 if (members == null)
2046 return MemberList.Empty;
2047 else
2048 return new MemberList (members);
2051 public override MemberCache MemberCache {
2052 get {
2053 return member_cache;
2057 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2058 MemberFilter filter, object criteria)
2060 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2062 if (ds != null)
2063 return ds.FindMembers (mt, bf, filter, criteria);
2064 else
2065 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2068 /// <summary>
2069 /// Emits the values for the constants
2070 /// </summary>
2071 public void EmitConstants ()
2073 if (constants != null)
2074 foreach (Const con in constants)
2075 con.Emit ();
2076 return;
2079 static void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2081 if (al == null)
2082 return;
2084 foreach (MemberCore mc in al) {
2085 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2086 continue;
2088 if (!mc.IsUsed) {
2089 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2094 public virtual void VerifyMembers ()
2097 // Check for internal or private fields that were never assigned
2099 if (RootContext.WarningLevel >= 3) {
2100 CheckMemberUsage (properties, "property");
2101 CheckMemberUsage (methods, "method");
2102 CheckMemberUsage (constants, "constant");
2104 if (fields != null){
2105 foreach (FieldMember f in fields) {
2106 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2107 continue;
2109 if (!f.IsUsed){
2110 if ((f.caching_flags & Flags.IsAssigned) == 0)
2111 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2112 else {
2113 #if NET_2_0
2114 const int error_code = 414;
2115 #else
2116 const int error_code = 169;
2117 #endif
2118 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2119 f.GetSignatureForError ());
2121 continue;
2125 // Only report 649 on level 4
2127 if (RootContext.WarningLevel < 4)
2128 continue;
2130 if ((f.caching_flags & Flags.IsAssigned) != 0)
2131 continue;
2133 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2134 f.GetSignatureForError (), f.Type.Type.IsValueType ? Activator.CreateInstance (f.Type.Type).ToString() : "null");
2140 // TODO: move to ClassOrStruct
2141 void EmitConstructors ()
2143 if (instance_constructors == null)
2144 return;
2146 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2147 bool has_compliant_args = false;
2149 foreach (Constructor c in instance_constructors) {
2150 c.Emit ();
2152 if (has_compliant_args)
2153 continue;
2155 has_compliant_args = c.HasCompliantArgs;
2157 if (!has_compliant_args)
2158 Report.Error (3015, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2159 } else {
2160 foreach (Constructor c in instance_constructors)
2161 c.Emit ();
2165 /// <summary>
2166 /// Emits the code, this step is performed after all
2167 /// the types, enumerations, constructors
2168 /// </summary>
2169 public virtual void EmitType ()
2171 if (OptAttributes != null)
2172 OptAttributes.Emit ();
2174 if (IsGeneric) {
2175 int offset = CountTypeParameters - CurrentTypeParameters.Length;
2176 for (int i = offset; i < gen_params.Length; i++)
2177 CurrentTypeParameters [i - offset].EmitAttributes ();
2181 // Structs with no fields need to have at least one byte.
2182 // The right thing would be to set the PackingSize in a DefineType
2183 // but there are no functions that allow interfaces *and* the size to
2184 // be specified.
2187 if (Kind == Kind.Struct && first_nonstatic_field == null){
2188 FieldBuilder fb = TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
2189 FieldAttributes.Private);
2191 if (HasExplicitLayout){
2192 object [] ctor_args = new object [1];
2193 ctor_args [0] = 0;
2195 CustomAttributeBuilder cba = new CustomAttributeBuilder (
2196 TypeManager.field_offset_attribute_ctor, ctor_args);
2197 fb.SetCustomAttribute (cba);
2201 Emit ();
2203 EmitConstructors ();
2205 // Can not continue if constants are broken
2206 EmitConstants ();
2207 if (Report.Errors > 0)
2208 return;
2210 if (default_static_constructor != null)
2211 default_static_constructor.Emit ();
2213 if (methods != null){
2214 foreach (Method m in methods)
2215 m.Emit ();
2218 if (operators != null)
2219 foreach (Operator o in operators)
2220 o.Emit ();
2222 if (properties != null)
2223 foreach (Property p in properties)
2224 p.Emit ();
2226 if (indexers != null){
2227 indexers.Emit ();
2230 if (fields != null)
2231 foreach (FieldMember f in fields)
2232 f.Emit ();
2234 if (events != null){
2235 foreach (Event e in Events)
2236 e.Emit ();
2239 if (delegates != null) {
2240 foreach (Delegate d in Delegates) {
2241 d.Emit ();
2245 if (enums != null) {
2246 foreach (Enum e in enums) {
2247 e.Emit ();
2251 if (pending != null)
2252 if (pending.VerifyPendingMethods ())
2253 return;
2255 if (iterators != null)
2256 foreach (Iterator iterator in iterators)
2257 iterator.EmitType ();
2260 public override void CloseType ()
2262 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2263 return;
2265 try {
2266 caching_flags |= Flags.CloseTypeCreated;
2267 TypeBuilder.CreateType ();
2268 } catch (TypeLoadException){
2270 // This is fine, the code still created the type
2272 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2273 // Console.WriteLine (e.Message);
2274 } catch {
2275 Console.WriteLine ("In type: " + Name);
2276 throw;
2279 if (Enums != null)
2280 foreach (Enum en in Enums)
2281 en.CloseType ();
2283 if (Types != null){
2284 foreach (TypeContainer tc in Types)
2285 if (tc.Kind == Kind.Struct)
2286 tc.CloseType ();
2288 foreach (TypeContainer tc in Types)
2289 if (tc.Kind != Kind.Struct)
2290 tc.CloseType ();
2293 if (Delegates != null)
2294 foreach (Delegate d in Delegates)
2295 d.CloseType ();
2297 if (Iterators != null)
2298 foreach (Iterator i in Iterators)
2299 i.CloseType ();
2301 types = null;
2302 properties = null;
2303 enums = null;
2304 delegates = null;
2305 fields = null;
2306 initialized_fields = null;
2307 initialized_static_fields = null;
2308 constants = null;
2309 interfaces = null;
2310 methods = null;
2311 events = null;
2312 indexers = null;
2313 operators = null;
2314 iterators = null;
2315 default_constructor = null;
2316 default_static_constructor = null;
2317 type_bases = null;
2318 OptAttributes = null;
2319 ifaces = null;
2320 base_cache = null;
2321 member_cache = null;
2325 // Performs the validation on a Method's modifiers (properties have
2326 // the same properties).
2328 public bool MethodModifiersValid (MemberCore mc)
2330 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2331 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2332 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2333 bool ok = true;
2334 int flags = mc.ModFlags;
2337 // At most one of static, virtual or override
2339 if ((flags & Modifiers.STATIC) != 0){
2340 if ((flags & vao) != 0){
2341 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2342 mc.GetSignatureForError ());
2343 ok = false;
2347 if (Kind == Kind.Struct){
2348 if ((flags & va) != 0){
2349 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2350 ok = false;
2354 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2355 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2356 mc.GetSignatureForError ());
2357 ok = false;
2361 // If the declaration includes the abstract modifier, then the
2362 // declaration does not include static, virtual or extern
2364 if ((flags & Modifiers.ABSTRACT) != 0){
2365 if ((flags & Modifiers.EXTERN) != 0){
2366 Report.Error (
2367 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2368 ok = false;
2371 if ((flags & Modifiers.SEALED) != 0) {
2372 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2373 ok = false;
2376 if ((flags & Modifiers.VIRTUAL) != 0){
2377 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2378 ok = false;
2381 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2382 Report.Error (513, mc.Location, "`{0}' is abstract but it is contained in nonabstract class", mc.GetSignatureForError ());
2383 ok = false;
2387 if ((flags & Modifiers.PRIVATE) != 0){
2388 if ((flags & vao) != 0){
2389 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2390 ok = false;
2394 if ((flags & Modifiers.SEALED) != 0){
2395 if ((flags & Modifiers.OVERRIDE) == 0){
2396 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2397 ok = false;
2401 return ok;
2404 public Constructor DefaultStaticConstructor {
2405 get { return default_static_constructor; }
2408 protected override bool VerifyClsCompliance ()
2410 if (!base.VerifyClsCompliance ())
2411 return false;
2413 VerifyClsName ();
2415 Type base_type = TypeBuilder.BaseType;
2416 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2417 Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2420 if (!Parent.IsClsComplianceRequired ()) {
2421 Report.Error (3018, Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
2422 GetSignatureForError (), Parent.GetSignatureForError ());
2424 return true;
2428 /// <summary>
2429 /// Checks whether container name is CLS Compliant
2430 /// </summary>
2431 void VerifyClsName ()
2433 Hashtable base_members = base_cache == null ?
2434 new Hashtable () :
2435 base_cache.GetPublicMembers ();
2436 Hashtable this_members = new Hashtable ();
2438 foreach (DictionaryEntry entry in defined_names) {
2439 MemberCore mc = (MemberCore)entry.Value;
2440 if (!mc.IsClsComplianceRequired ())
2441 continue;
2443 string name = (string) entry.Key;
2444 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2446 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2447 object found = base_members [lcase];
2448 if (found == null) {
2449 found = this_members [lcase];
2450 if (found == null) {
2451 this_members.Add (lcase, mc);
2452 continue;
2456 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2457 continue;
2459 if (found is MemberInfo) {
2460 if (basename == ((MemberInfo) found).Name)
2461 continue;
2462 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2463 } else {
2464 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2466 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2471 /// <summary>
2472 /// Performs checks for an explicit interface implementation. First it
2473 /// checks whether the `interface_type' is a base inteface implementation.
2474 /// Then it checks whether `name' exists in the interface type.
2475 /// </summary>
2476 public virtual bool VerifyImplements (MemberBase mb)
2478 if (ifaces != null) {
2479 foreach (Type t in ifaces){
2480 if (t == mb.InterfaceType)
2481 return true;
2485 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2486 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2487 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2488 return false;
2491 public void Mark_HasEquals ()
2493 Methods.HasEquals = true;
2496 public void Mark_HasGetHashCode ()
2498 Methods.HasGetHashCode = true;
2502 // IMemberContainer
2505 string IMemberContainer.Name {
2506 get {
2507 return Name;
2511 Type IMemberContainer.Type {
2512 get {
2513 return TypeBuilder;
2517 MemberCache IMemberContainer.MemberCache {
2518 get {
2519 return member_cache;
2523 bool IMemberContainer.IsInterface {
2524 get {
2525 return Kind == Kind.Interface;
2529 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2531 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2533 if (GenericType != null)
2534 return TypeManager.FindMembers (GenericType, mt, new_bf,
2535 null, null);
2536 else
2537 return FindMembers (mt, new_bf, null, null);
2541 // Generates xml doc comments (if any), and if required,
2542 // handle warning report.
2544 internal override void GenerateDocComment (DeclSpace ds)
2546 DocUtil.GenerateTypeDocComment (this, ds);
2549 public override string DocCommentHeader {
2550 get { return "T:"; }
2553 public virtual MemberCache BaseCache {
2554 get {
2555 if (base_cache != null)
2556 return base_cache;
2557 if (TypeBuilder.BaseType != null)
2558 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2559 if (TypeBuilder.IsInterface)
2560 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2561 return base_cache;
2567 public abstract class ClassOrStruct : TypeContainer {
2568 ListDictionary declarative_security;
2570 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2571 MemberName name, Attributes attrs, Kind kind)
2572 : base (ns, parent, name, attrs, kind)
2576 protected override bool AddToContainer (MemberCore symbol, string name)
2578 if (name == MemberName.Name) {
2579 if (symbol is TypeParameter) {
2580 Report.Error (694, symbol.Location,
2581 "Type parameter `{0}' has same name as " +
2582 "containing type, or method", name);
2583 return false;
2586 Report.SymbolRelatedToPreviousError (this);
2587 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2588 symbol.GetSignatureForError ());
2589 return false;
2592 return base.AddToContainer (symbol, name);
2595 public override void VerifyMembers ()
2597 base.VerifyMembers ();
2599 if ((events != null) && (RootContext.WarningLevel >= 3)) {
2600 foreach (Event e in events){
2601 if ((e.caching_flags & Flags.IsAssigned) == 0)
2602 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2607 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2609 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2610 if (declarative_security == null)
2611 declarative_security = new ListDictionary ();
2613 a.ExtractSecurityPermissionSet (declarative_security);
2614 return;
2617 if (a.Type == TypeManager.struct_layout_attribute_type && a.GetLayoutKindValue () == LayoutKind.Explicit) {
2618 HasExplicitLayout = true;
2621 base.ApplyAttributeBuilder (a, cb);
2624 /// <summary>
2625 /// Defines the default constructors
2626 /// </summary>
2627 protected void DefineDefaultConstructor (bool is_static)
2629 // The default instance constructor is public
2630 // If the class is abstract, the default constructor is protected
2631 // The default static constructor is private
2633 int mods;
2634 if (is_static) {
2635 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2636 } else {
2637 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2640 Constructor c = new Constructor (this, MemberName.Name, mods,
2641 Parameters.EmptyReadOnlyParameters,
2642 new GeneratedBaseInitializer (Location),
2643 Location);
2645 AddConstructor (c);
2646 c.Block = new ToplevelBlock (null, Location);
2649 void DefineFieldInitializers ()
2651 if (initialized_fields != null) {
2652 for (int i = 0; i < initialized_fields.Count; ++i) {
2653 FieldBase fb = (FieldBase)initialized_fields[i];
2654 fb.ResolveInitializer ();
2655 if (fb.HasDefaultInitializer && RootContext.Optimize) {
2656 // Field is re-initialized to its default value => removed
2657 initialized_fields.RemoveAt (i);
2658 --i;
2663 if (initialized_static_fields != null) {
2664 bool has_complex_initializer = false;
2666 foreach (FieldBase fb in initialized_static_fields) {
2667 if (fb.ResolveInitializer () is Constant)
2668 continue;
2670 has_complex_initializer = true;
2673 // Need special check to not optimize code like this
2674 // static int a = b = 5;
2675 // static int b = 0;
2676 if (!has_complex_initializer && RootContext.Optimize) {
2677 for (int i = 0; i < initialized_static_fields.Count; ++i) {
2678 FieldBase fb = (FieldBase)initialized_static_fields[i];
2679 if (fb.HasDefaultInitializer) {
2680 initialized_static_fields.RemoveAt (i);
2681 --i;
2686 if (default_static_constructor == null && initialized_static_fields.Count > 0) {
2687 DefineDefaultConstructor (true);
2693 public override bool Define ()
2695 DefineFieldInitializers ();
2697 if (default_static_constructor != null)
2698 default_static_constructor.Define ();
2700 return base.Define ();
2703 public override void Emit ()
2705 base.Emit ();
2707 if (declarative_security != null) {
2708 foreach (DictionaryEntry de in declarative_security) {
2709 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2714 protected override TypeAttributes TypeAttr {
2715 get {
2716 if (default_static_constructor == null)
2717 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2719 return base.TypeAttr;
2725 // TODO: should be sealed
2726 public class Class : ClassOrStruct {
2727 const int AllowedModifiers =
2728 Modifiers.NEW |
2729 Modifiers.PUBLIC |
2730 Modifiers.PROTECTED |
2731 Modifiers.INTERNAL |
2732 Modifiers.PRIVATE |
2733 Modifiers.ABSTRACT |
2734 Modifiers.SEALED |
2735 Modifiers.STATIC |
2736 Modifiers.UNSAFE;
2738 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2739 Attributes attrs)
2740 : base (ns, parent, name, attrs, Kind.Class)
2742 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2743 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2745 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2746 Report.FeatureIsNotStandardized (Location, "static classes");
2750 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2752 if (a.Type == TypeManager.attribute_usage_type) {
2753 if (BaseType != TypeManager.attribute_type && !BaseType.IsSubclassOf (TypeManager.attribute_type) &&
2754 TypeBuilder.FullName != "System.Attribute") {
2755 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2759 if (a.Type == TypeManager.conditional_attribute_type &&
2760 !(BaseType == TypeManager.attribute_type || BaseType.IsSubclassOf (TypeManager.attribute_type))) {
2761 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2762 return;
2765 if (a.Type == TypeManager.comimport_attr_type &&
2766 !attributes.Contains (TypeManager.guid_attr_type)) {
2767 a.Error_MissingGuidAttribute ();
2768 return;
2771 if (AttributeTester.IsAttributeExcluded (a.Type))
2772 return;
2774 base.ApplyAttributeBuilder (a, cb);
2777 public override AttributeTargets AttributeTargets {
2778 get {
2779 return AttributeTargets.Class;
2783 protected override void DefineContainerMembers (MemberCoreArrayList list)
2785 if (list == null)
2786 return;
2788 if (!IsStatic) {
2789 base.DefineContainerMembers (list);
2790 return;
2793 foreach (MemberCore m in list) {
2794 if (m is Operator) {
2795 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2796 continue;
2799 if (m is Destructor) {
2800 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2801 continue;
2804 if ((m.ModFlags & Modifiers.PROTECTED) != 0) {
2805 Report.Error (1057, m.Location, "`{0}': Static classes cannot contain protected members", m.GetSignatureForError ());
2806 continue;
2809 if (m is Indexer) {
2810 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2811 continue;
2814 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2815 continue;
2817 if (m is Constructor) {
2818 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2819 continue;
2822 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2825 base.DefineContainerMembers (list);
2828 public override TypeBuilder DefineType ()
2830 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2831 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2832 return null;
2835 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2836 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2837 return null;
2840 return base.DefineType ();
2843 protected override bool DoDefineMembers ()
2845 if (InstanceConstructors == null && !IsStatic)
2846 DefineDefaultConstructor (false);
2848 return base.DoDefineMembers ();
2851 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
2853 TypeExpr[] ifaces = base.GetClassBases (out base_class);
2855 if (base_class == null) {
2856 if (RootContext.StdLib)
2857 base_class = TypeManager.system_object_expr;
2858 else if (Name != "System.Object")
2859 base_class = TypeManager.system_object_expr;
2860 } else {
2861 if (Kind == Kind.Class && base_class is TypeParameterExpr){
2862 Report.Error (
2863 689, base_class.Location,
2864 "Cannot derive from `{0}' because it is a type parameter",
2865 base_class.GetSignatureForError ());
2866 return ifaces;
2869 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
2870 Report.Error (1521, base_class.Location, "Invalid base type");
2871 return ifaces;
2874 if (base_class.IsSealed){
2875 Report.SymbolRelatedToPreviousError (base_class.Type);
2876 if (base_class.Type.IsAbstract) {
2877 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2878 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2879 } else {
2880 Report.Error (509, Location, "`{0}': cannot derive from sealed class `{1}'",
2881 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2883 return ifaces;
2886 if (!base_class.CanInheritFrom ()){
2887 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2888 GetSignatureForError (), base_class.GetSignatureForError ());
2889 return ifaces;
2892 if (!base_class.AsAccessible (this, ModFlags)) {
2893 Report.SymbolRelatedToPreviousError (base_class.Type);
2894 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2895 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2899 if (IsStatic) {
2900 if (base_class != TypeManager.system_object_expr) {
2901 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2902 GetSignatureForError (), base_class.GetSignatureForError ());
2903 return ifaces;
2906 if (ifaces != null) {
2907 foreach (TypeExpr t in ifaces)
2908 Report.SymbolRelatedToPreviousError (t.Type);
2909 Report.Error (714, Location, "`{0}': static classes cannot implement interfaces", GetSignatureForError ());
2913 return ifaces;
2916 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2917 /// Valid only for attribute classes.
2918 public bool IsExcluded ()
2920 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2921 return (caching_flags & Flags.Excluded) != 0;
2923 caching_flags &= ~Flags.Excluded_Undetected;
2925 if (OptAttributes == null)
2926 return false;
2928 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
2930 if (attrs == null)
2931 return false;
2933 foreach (Attribute a in attrs) {
2934 string condition = a.GetConditionalAttributeValue ();
2935 if (RootContext.AllDefines.Contains (condition))
2936 return false;
2939 caching_flags |= Flags.Excluded;
2940 return true;
2943 bool IsStatic {
2944 get {
2945 return (ModFlags & Modifiers.STATIC) != 0;
2950 // FIXME: How do we deal with the user specifying a different
2951 // layout?
2953 protected override TypeAttributes TypeAttr {
2954 get {
2955 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2956 if (IsStatic)
2957 ta |= TypeAttributes.Abstract | TypeAttributes.Sealed;
2958 return ta;
2963 public sealed class Struct : ClassOrStruct {
2964 // <summary>
2965 // Modifiers allowed in a struct declaration
2966 // </summary>
2967 const int AllowedModifiers =
2968 Modifiers.NEW |
2969 Modifiers.PUBLIC |
2970 Modifiers.PROTECTED |
2971 Modifiers.INTERNAL |
2972 Modifiers.UNSAFE |
2973 Modifiers.PRIVATE;
2975 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2976 int mod, Attributes attrs)
2977 : base (ns, parent, name, attrs, Kind.Struct)
2979 int accmods;
2981 if (parent.Parent == null)
2982 accmods = Modifiers.INTERNAL;
2983 else
2984 accmods = Modifiers.PRIVATE;
2986 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2988 this.ModFlags |= Modifiers.SEALED;
2991 public override AttributeTargets AttributeTargets {
2992 get {
2993 return AttributeTargets.Struct;
2997 const TypeAttributes DefaultTypeAttributes =
2998 TypeAttributes.SequentialLayout |
2999 TypeAttributes.Sealed |
3000 TypeAttributes.BeforeFieldInit;
3003 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
3005 TypeExpr[] ifaces = base.GetClassBases (out base_class);
3007 // If we are compiling our runtime,
3008 // and we are defining ValueType, then our
3009 // base is `System.Object'.
3011 if (base_class == null) {
3012 if (!RootContext.StdLib && Name == "System.ValueType")
3013 base_class = TypeManager.system_object_expr;
3014 else
3015 base_class = TypeManager.system_valuetype_expr;
3018 return ifaces;
3022 // FIXME: Allow the user to specify a different set of attributes
3023 // in some cases (Sealed for example is mandatory for a class,
3024 // but what SequentialLayout can be changed
3026 protected override TypeAttributes TypeAttr {
3027 get {
3028 return base.TypeAttr | DefaultTypeAttributes;
3032 public override void RegisterFieldForInitialization (FieldBase field)
3034 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3035 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3036 field.GetSignatureForError ());
3037 return;
3039 base.RegisterFieldForInitialization (field);
3044 /// <summary>
3045 /// Interfaces
3046 /// </summary>
3047 public sealed class Interface : TypeContainer, IMemberContainer {
3049 /// <summary>
3050 /// Modifiers allowed in a class declaration
3051 /// </summary>
3052 public const int AllowedModifiers =
3053 Modifiers.NEW |
3054 Modifiers.PUBLIC |
3055 Modifiers.PROTECTED |
3056 Modifiers.INTERNAL |
3057 Modifiers.UNSAFE |
3058 Modifiers.PRIVATE;
3060 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
3061 Attributes attrs)
3062 : base (ns, parent, name, attrs, Kind.Interface)
3064 int accmods;
3066 if (parent.Parent == null)
3067 accmods = Modifiers.INTERNAL;
3068 else
3069 accmods = Modifiers.PRIVATE;
3071 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
3074 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3076 if (a.Type == TypeManager.comimport_attr_type &&
3077 !attributes.Contains (TypeManager.guid_attr_type)) {
3078 a.Error_MissingGuidAttribute ();
3079 return;
3081 base.ApplyAttributeBuilder (a, cb);
3085 public override AttributeTargets AttributeTargets {
3086 get {
3087 return AttributeTargets.Interface;
3091 const TypeAttributes DefaultTypeAttributes =
3092 TypeAttributes.AutoLayout |
3093 TypeAttributes.Abstract |
3094 TypeAttributes.Interface;
3096 protected override TypeAttributes TypeAttr {
3097 get {
3098 return base.TypeAttr | DefaultTypeAttributes;
3102 protected override bool VerifyClsCompliance ()
3104 if (!base.VerifyClsCompliance ())
3105 return false;
3107 if (ifaces != null) {
3108 foreach (Type t in ifaces) {
3109 if (AttributeTester.IsClsCompliant (t))
3110 continue;
3112 Report.SymbolRelatedToPreviousError (t);
3113 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3114 GetSignatureForError (), TypeManager.CSharpName (t));
3118 return true;
3122 public abstract class MethodCore : MemberBase {
3123 public readonly Parameters Parameters;
3124 protected ToplevelBlock block;
3127 // The method we're overriding if this is an override method.
3129 protected MethodInfo base_method = null;
3131 public MethodCore (DeclSpace parent, GenericMethod generic,
3132 Expression type, int mod, int allowed_mod, bool is_iface,
3133 MemberName name, Attributes attrs, Parameters parameters)
3134 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3135 name, attrs)
3137 Parameters = parameters;
3138 IsInterface = is_iface;
3142 // Returns the System.Type array for the parameters of this method
3144 public Type [] ParameterTypes {
3145 get {
3146 return Parameters.Types;
3150 public Parameters ParameterInfo
3152 get {
3153 return Parameters;
3157 public ToplevelBlock Block {
3158 get {
3159 return block;
3162 set {
3163 block = value;
3167 public void SetYields ()
3169 ModFlags |= Modifiers.METHOD_YIELDS;
3172 protected override bool CheckBase ()
3174 if (!base.CheckBase ())
3175 return false;
3177 // Check whether arguments were correct.
3178 if (!DoDefineParameters ())
3179 return false;
3181 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
3182 return false;
3184 if (IsExplicitImpl)
3185 return true;
3187 // Is null for System.Object while compiling corlib and base interfaces
3188 if (ParentContainer.BaseCache == null) {
3189 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3190 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3192 return true;
3195 Type base_ret_type = null;
3196 base_method = FindOutBaseMethod (ref base_ret_type);
3198 // method is override
3199 if (base_method != null) {
3201 if (!CheckMethodAgainstBase ())
3202 return false;
3204 if ((ModFlags & Modifiers.NEW) == 0) {
3205 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_ret_type))) {
3206 Report.SymbolRelatedToPreviousError (base_method);
3207 if (this is PropertyBase) {
3208 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3209 GetSignatureForError (), TypeManager.CSharpName (base_ret_type), TypeManager.CSharpSignature (base_method));
3211 else {
3212 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3213 GetSignatureForError (), TypeManager.CSharpName (base_ret_type), TypeManager.CSharpSignature (base_method));
3215 return false;
3217 } else {
3218 if (base_method.IsAbstract && !IsInterface) {
3219 Report.SymbolRelatedToPreviousError (base_method);
3220 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3221 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3222 return false;
3226 if (base_method.IsSpecialName && !(this is PropertyBase)) {
3227 Report.Error (115, Location, "`{0}': no suitable method found to override", GetSignatureForError ());
3228 return false;
3231 if (Name == "Equals" && Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type)
3232 ParentContainer.Mark_HasEquals ();
3233 else if (Name == "GetHashCode" && Parameters.Empty)
3234 ParentContainer.Mark_HasGetHashCode ();
3236 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3237 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3238 if (oa != null) {
3239 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type)) {
3240 Report.SymbolRelatedToPreviousError (base_method);
3241 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3242 GetSignatureForError (), TypeManager.CSharpSignature (base_method) );
3246 return true;
3249 MemberInfo conflict_symbol = ParentContainer.FindBaseMemberWithSameName (Name, !(this is Property));
3250 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3251 if (conflict_symbol != null) {
3252 Report.SymbolRelatedToPreviousError (conflict_symbol);
3253 if (this is PropertyBase)
3254 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3255 else
3256 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3257 } else
3258 Report.Error (115, Location, "`{0}': no suitable method found to override", GetSignatureForError ());
3259 return false;
3262 if (conflict_symbol == null) {
3263 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3264 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3266 return true;
3269 if ((ModFlags & Modifiers.NEW) == 0) {
3270 if (this is Method && conflict_symbol is MethodBase)
3271 return true;
3273 Report.SymbolRelatedToPreviousError (conflict_symbol);
3274 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3275 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3278 return true;
3282 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3283 // that have been defined.
3285 // `name' is the user visible name for reporting errors (this is used to
3286 // provide the right name regarding method names and properties)
3288 bool CheckMethodAgainstBase ()
3290 bool ok = true;
3292 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3293 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3294 Report.Error (506, Location,
3295 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3296 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3297 ok = false;
3300 // Now we check that the overriden method is not final
3302 if (base_method.IsFinal) {
3303 Report.SymbolRelatedToPreviousError (base_method);
3304 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3305 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3306 ok = false;
3309 // Check that the permissions are not being changed
3311 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3312 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3314 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3315 Error_CannotChangeAccessModifiers (base_method, base_classp, null);
3316 ok = false;
3320 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
3321 ModFlags |= Modifiers.NEW;
3322 Report.SymbolRelatedToPreviousError (base_method);
3323 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3324 Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
3325 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3326 } else {
3327 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3328 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3332 return ok;
3335 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3337 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3339 // when overriding protected internal, the method can be declared
3340 // protected internal only within the same assembly
3343 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3344 if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3346 // assemblies differ - report an error
3349 return false;
3350 } else if (thisp != base_classp) {
3352 // same assembly, but other attributes differ - report an error
3355 return false;
3357 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3359 // if it's not "protected internal", it must be "protected"
3362 return false;
3363 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3365 // protected within the same assembly - an error
3367 return false;
3368 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3369 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3371 // protected ok, but other attributes differ - report an error
3373 return false;
3375 return true;
3376 } else {
3377 return (thisp == base_classp);
3381 public bool CheckAbstractAndExtern (bool has_block)
3383 if (ParentContainer.Kind == Kind.Interface)
3384 return true;
3386 if (has_block) {
3387 if ((ModFlags & Modifiers.EXTERN) != 0) {
3388 Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
3389 GetSignatureForError ());
3390 return false;
3393 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
3394 Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
3395 GetSignatureForError ());
3396 return false;
3398 } else {
3399 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
3400 Report.Error (501, Location, "`{0}' must declare a body because it is not marked abstract or extern",
3401 GetSignatureForError ());
3402 return false;
3406 return true;
3409 protected void Error_CannotChangeAccessModifiers (MemberInfo base_method, MethodAttributes ma, string suffix)
3411 Report.SymbolRelatedToPreviousError (base_method);
3412 string base_name = TypeManager.GetFullNameSignature (base_method);
3413 string this_name = GetSignatureForError ();
3414 if (suffix != null) {
3415 base_name += suffix;
3416 this_name += suffix;
3419 Report.Error (507, Location, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3420 this_name, Modifiers.GetDescription (ma), base_name);
3423 protected static string Error722 {
3424 get {
3425 return "`{0}': static types cannot be used as return types";
3429 /// <summary>
3430 /// For custom member duplication search in a container
3431 /// </summary>
3432 protected abstract bool CheckForDuplications ();
3434 /// <summary>
3435 /// Gets base method and its return type
3436 /// </summary>
3437 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3439 protected bool DoDefineParameters ()
3441 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
3443 // Check if arguments were correct
3444 if (!Parameters.Resolve (rc))
3445 return false;
3447 return CheckParameters (ParameterTypes);
3450 bool CheckParameters (Type [] parameters)
3452 bool error = false;
3454 foreach (Type partype in parameters){
3455 if (partype == TypeManager.void_type) {
3456 Report.Error (
3457 1547, Location, "Keyword 'void' cannot " +
3458 "be used in this context");
3459 return false;
3462 if (partype.IsPointer){
3463 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3464 error = true;
3467 if (ds.AsAccessible (partype, ModFlags))
3468 continue;
3470 Report.SymbolRelatedToPreviousError (partype);
3471 if (this is Indexer)
3472 Report.Error (55, Location,
3473 "Inconsistent accessibility: parameter type `" +
3474 TypeManager.CSharpName (partype) + "' is less " +
3475 "accessible than indexer `" + GetSignatureForError () + "'");
3476 else if (this is Operator)
3477 Report.Error (57, Location,
3478 "Inconsistent accessibility: parameter type `" +
3479 TypeManager.CSharpName (partype) + "' is less " +
3480 "accessible than operator `" + GetSignatureForError () + "'");
3481 else
3482 Report.Error (51, Location,
3483 "Inconsistent accessibility: parameter type `" +
3484 TypeManager.CSharpName (partype) + "' is less " +
3485 "accessible than method `" + GetSignatureForError () + "'");
3486 error = true;
3489 return !error;
3492 protected override bool VerifyClsCompliance ()
3494 if (!base.VerifyClsCompliance ()) {
3495 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3496 Report.Error (3011, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3498 return false;
3501 if (Parameters.HasArglist) {
3502 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3505 if (!AttributeTester.IsClsCompliant (MemberType)) {
3506 if (this is PropertyBase)
3507 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3508 GetSignatureForError ());
3509 else
3510 Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant",
3511 GetSignatureForError ());
3514 Parameters.VerifyClsCompliance ();
3516 return true;
3519 protected bool IsDuplicateImplementation (MethodCore method)
3521 if (method == this || !(method.MemberName.Equals (MemberName)))
3522 return false;
3524 Type[] param_types = method.ParameterTypes;
3525 // This never happen. Rewrite this as Equal
3526 if (param_types == null && ParameterTypes == null)
3527 return true;
3528 if (param_types == null || ParameterTypes == null)
3529 return false;
3531 if (param_types.Length != ParameterTypes.Length)
3532 return false;
3534 if (method.Parameters.HasArglist != Parameters.HasArglist)
3535 return false;
3537 bool equal = true;
3539 for (int i = 0; i < param_types.Length; i++) {
3540 if (param_types [i] != ParameterTypes [i])
3541 equal = false;
3544 if (IsExplicitImpl && (method.InterfaceType != InterfaceType))
3545 equal = false;
3547 // TODO: make operator compatible with MethodCore to avoid this
3548 if (this is Operator && method is Operator) {
3549 if (MemberType != method.MemberType)
3550 equal = false;
3553 if (equal) {
3555 // Try to report 663: method only differs on out/ref
3557 Parameters info = ParameterInfo;
3558 Parameters other_info = method.ParameterInfo;
3559 for (int i = 0; i < info.Count; i++){
3560 try {
3561 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3562 Report.SymbolRelatedToPreviousError (method);
3563 Report.Error (663, Location, "`{0}': Methods cannot differ only on their use of ref and out on a parameters",
3564 GetSignatureForError ());
3565 return false;
3566 }} catch {
3567 Console.WriteLine ("Method is: {0} {1}", method.Location, method);
3568 Console.WriteLine ("this is: {0} {1}", Location, this);
3572 Report.SymbolRelatedToPreviousError (method);
3573 if (this is Operator && method is Operator)
3574 Report.Error (557, Location, "Duplicate user-defined conversion in type `{0}'", Parent.Name);
3575 else
3576 Report.Error (111, Location, TypeContainer.Error111, GetSignatureForError ());
3578 return true;
3581 return false;
3584 public override bool IsUsed {
3585 get { return IsExplicitImpl || base.IsUsed; }
3589 // Returns a string that represents the signature for this
3590 // member which should be used in XML documentation.
3592 public override string GetDocCommentName (DeclSpace ds)
3594 return DocUtil.GetMethodDocCommentName (this, ds);
3598 // Raised (and passed an XmlElement that contains the comment)
3599 // when GenerateDocComment is writing documentation expectedly.
3601 // FIXME: with a few effort, it could be done with XmlReader,
3602 // that means removal of DOM use.
3604 internal override void OnGenerateDocComment (XmlElement el)
3606 DocUtil.OnMethodGenerateDocComment (this, el);
3610 // Represents header string for documentation comment.
3612 public override string DocCommentHeader {
3613 get { return "M:"; }
3618 public abstract class MethodOrOperator : MethodCore, IMethodData
3620 public MethodBuilder MethodBuilder;
3621 ReturnParameter return_attributes;
3622 ListDictionary declarative_security;
3623 protected MethodData MethodData;
3625 static string[] attribute_targets = new string [] { "method", "return" };
3627 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, Expression type, int mod,
3628 int allowed_mod, bool is_interface, MemberName name,
3629 Attributes attrs, Parameters parameters)
3630 : base (parent, generic, type, mod, allowed_mod, is_interface, name,
3631 attrs, parameters)
3635 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3637 if (a.Target == AttributeTargets.ReturnValue) {
3638 if (return_attributes == null)
3639 return_attributes = new ReturnParameter (MethodBuilder, Location);
3641 return_attributes.ApplyAttributeBuilder (a, cb);
3642 return;
3645 if (a.Type == TypeManager.methodimpl_attr_type &&
3646 (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
3647 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3650 if (a.Type == TypeManager.dllimport_type) {
3651 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3652 if ((ModFlags & extern_static) != extern_static) {
3653 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3656 return;
3659 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
3660 if (declarative_security == null)
3661 declarative_security = new ListDictionary ();
3662 a.ExtractSecurityPermissionSet (declarative_security);
3663 return;
3666 MethodBuilder.SetCustomAttribute (cb);
3669 public override AttributeTargets AttributeTargets {
3670 get {
3671 return AttributeTargets.Method;
3675 public EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
3677 EmitContext ec = new EmitContext (this,
3678 tc, this.ds, Location, ig, MemberType, ModFlags, false);
3680 Iterator iterator = tc as Iterator;
3681 if (iterator != null)
3682 ec.CurrentAnonymousMethod = iterator.Host;
3684 return ec;
3687 public override bool Define ()
3689 if (!DoDefineBase ())
3690 return false;
3692 MethodBuilder mb = null;
3693 if (GenericMethod != null) {
3694 string method_name = MemberName.Name;
3696 if (IsExplicitImpl) {
3697 method_name = TypeManager.CSharpName (InterfaceType) +
3698 '.' + method_name;
3701 mb = Parent.TypeBuilder.DefineMethod (method_name, flags);
3703 if (!GenericMethod.Define (mb))
3704 return false;
3707 if (!DoDefine ())
3708 return false;
3710 if (!CheckAbstractAndExtern (block != null))
3711 return false;
3713 if (!CheckBase ())
3714 return false;
3716 MethodData = new MethodData (this, ModFlags, flags, this, mb, GenericMethod, base_method);
3718 if (!MethodData.Define (ParentContainer))
3719 return false;
3721 MethodBuilder = MethodData.MethodBuilder;
3723 if (MemberType.IsAbstract && MemberType.IsSealed) {
3724 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
3725 return false;
3728 return true;
3731 public override void Emit ()
3733 if (OptAttributes != null)
3734 OptAttributes.Emit ();
3736 if (declarative_security != null) {
3737 foreach (DictionaryEntry de in declarative_security) {
3738 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3742 base.Emit ();
3745 protected void Error_ConditionalAttributeIsNotValid ()
3747 Report.Error (577, Location,
3748 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
3749 GetSignatureForError ());
3752 public override bool MarkForDuplicationCheck ()
3754 caching_flags |= Flags.TestMethodDuplication;
3755 return true;
3758 public override string[] ValidAttributeTargets {
3759 get {
3760 return attribute_targets;
3764 #region IMethodData Members
3766 public CallingConventions CallingConventions {
3767 get {
3768 CallingConventions cc = Parameters.CallingConvention;
3769 if (Parameters.HasArglist)
3770 block.HasVarargs = true;
3772 if (!IsInterface)
3773 if ((ModFlags & Modifiers.STATIC) == 0)
3774 cc |= CallingConventions.HasThis;
3776 // FIXME: How is `ExplicitThis' used in C#?
3778 return cc;
3782 public Type ReturnType {
3783 get {
3784 return MemberType;
3788 public MemberName MethodName {
3789 get {
3790 return MemberName;
3794 public new Location Location {
3795 get {
3796 return base.Location;
3800 protected override bool CheckBase() {
3801 if (!base.CheckBase ())
3802 return false;
3804 // TODO: Destructor should derive from MethodCore
3805 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == "Finalize" &&
3806 base_method.DeclaringType == TypeManager.object_type && !(this is Destructor)) {
3807 Report.Error (249, Location, "Do not override object.Finalize. Instead, provide a destructor");
3808 return false;
3811 return true;
3814 /// <summary>
3815 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3816 /// </summary>
3817 public bool IsExcluded () {
3818 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3819 return (caching_flags & Flags.Excluded) != 0;
3821 caching_flags &= ~Flags.Excluded_Undetected;
3823 if (base_method == null) {
3824 if (OptAttributes == null)
3825 return false;
3827 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
3829 if (attrs == null)
3830 return false;
3832 foreach (Attribute a in attrs) {
3833 string condition = a.GetConditionalAttributeValue ();
3834 if (condition == null)
3835 return false;
3837 if (RootContext.AllDefines.Contains (condition))
3838 return false;
3841 caching_flags |= Flags.Excluded;
3842 return true;
3845 IMethodData md = TypeManager.GetMethod (base_method);
3846 if (md == null) {
3847 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
3848 caching_flags |= Flags.Excluded;
3849 return true;
3851 return false;
3854 if (md.IsExcluded ()) {
3855 caching_flags |= Flags.Excluded;
3856 return true;
3858 return false;
3861 GenericMethod IMethodData.GenericMethod {
3862 get {
3863 return GenericMethod;
3867 #endregion
3871 public class SourceMethod : ISourceMethod
3873 DeclSpace parent;
3874 MethodBase builder;
3876 protected SourceMethod (DeclSpace parent, MethodBase builder,
3877 ISourceFile file, Location start, Location end)
3879 this.parent = parent;
3880 this.builder = builder;
3882 CodeGen.SymbolWriter.OpenMethod (file, this, start.Row, start.Column, end.Row, start.Column);
3885 public string Name {
3886 get { return builder.Name; }
3889 public int NamespaceID {
3890 get { return parent.NamespaceEntry.SymbolFileID; }
3893 public int Token {
3894 get {
3895 if (builder is MethodBuilder)
3896 return ((MethodBuilder) builder).GetToken ().Token;
3897 else if (builder is ConstructorBuilder)
3898 return ((ConstructorBuilder) builder).GetToken ().Token;
3899 else
3900 throw new NotSupportedException ();
3904 public void CloseMethod ()
3906 if (CodeGen.SymbolWriter != null)
3907 CodeGen.SymbolWriter.CloseMethod ();
3910 public static SourceMethod Create (DeclSpace parent, MethodBase builder, Block block)
3912 if (CodeGen.SymbolWriter == null)
3913 return null;
3914 if (block == null)
3915 return null;
3917 Location start_loc = block.StartLocation;
3918 if (start_loc.IsNull)
3919 return null;
3921 Location end_loc = block.EndLocation;
3922 if (end_loc.IsNull)
3923 return null;
3925 ISourceFile file = start_loc.SourceFile;
3926 if (file == null)
3927 return null;
3929 return new SourceMethod (
3930 parent, builder, file, start_loc, end_loc);
3934 public class Method : MethodOrOperator, IIteratorContainer {
3936 /// <summary>
3937 /// Modifiers allowed in a class declaration
3938 /// </summary>
3939 const int AllowedModifiers =
3940 Modifiers.NEW |
3941 Modifiers.PUBLIC |
3942 Modifiers.PROTECTED |
3943 Modifiers.INTERNAL |
3944 Modifiers.PRIVATE |
3945 Modifiers.STATIC |
3946 Modifiers.VIRTUAL |
3947 Modifiers.SEALED |
3948 Modifiers.OVERRIDE |
3949 Modifiers.ABSTRACT |
3950 Modifiers.UNSAFE |
3951 Modifiers.METHOD_YIELDS |
3952 Modifiers.EXTERN;
3954 const int AllowedInterfaceModifiers =
3955 Modifiers.NEW | Modifiers.UNSAFE;
3958 // return_type can be "null" for VOID values.
3960 public Method (DeclSpace parent, GenericMethod generic,
3961 Expression return_type, int mod, bool is_iface,
3962 MemberName name, Parameters parameters, Attributes attrs)
3963 : base (parent, generic, return_type, mod,
3964 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3965 is_iface, name, attrs, parameters)
3969 public override string GetSignatureForError()
3971 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
3974 void Error_DuplicateEntryPoint (MethodInfo b, Location location)
3976 Report.Error (17, location,
3977 "Program `{0}' has more than one entry point defined: `{1}'",
3978 CodeGen.FileName, TypeManager.CSharpSignature(b));
3981 bool IsEntryPoint (MethodBuilder b, Parameters pinfo)
3983 if (b.ReturnType != TypeManager.void_type &&
3984 b.ReturnType != TypeManager.int32_type)
3985 return false;
3987 if (pinfo.Count == 0)
3988 return true;
3990 if (pinfo.Count > 1)
3991 return false;
3993 Type t = pinfo.ParameterType(0);
3994 if (t.IsArray &&
3995 (t.GetArrayRank() == 1) &&
3996 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3997 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3998 return true;
3999 else
4000 return false;
4003 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4005 if (a.Type == TypeManager.conditional_attribute_type) {
4006 if (IsExplicitImpl) {
4007 Error_ConditionalAttributeIsNotValid ();
4008 return;
4011 if (ReturnType != TypeManager.void_type) {
4012 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4013 return;
4016 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4017 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4018 return;
4021 if (IsInterface) {
4022 Report.Error (582, Location, "Conditional not valid on interface members");
4023 return;
4026 if (MethodData.implementing != null) {
4027 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4028 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4029 return;
4032 for (int i = 0; i < ParameterInfo.Count; ++i) {
4033 if ((ParameterInfo.ParameterModifier (i) & Parameter.Modifier.OUTMASK) != 0) {
4034 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4035 return;
4040 base.ApplyAttributeBuilder (a, cb);
4043 protected override bool CheckForDuplications ()
4045 ArrayList ar = ParentContainer.Methods;
4046 if (ar != null) {
4047 int arLen = ar.Count;
4049 for (int i = 0; i < arLen; i++) {
4050 Method m = (Method) ar [i];
4051 if (IsDuplicateImplementation (m))
4052 return false;
4056 ar = ParentContainer.Properties;
4057 if (ar != null) {
4058 for (int i = 0; i < ar.Count; ++i) {
4059 PropertyBase pb = (PropertyBase) ar [i];
4060 if (pb.AreAccessorsDuplicateImplementation (this))
4061 return false;
4065 ar = ParentContainer.Indexers;
4066 if (ar != null) {
4067 for (int i = 0; i < ar.Count; ++i) {
4068 PropertyBase pb = (PropertyBase) ar [i];
4069 if (pb.AreAccessorsDuplicateImplementation (this))
4070 return false;
4074 ar = ParentContainer.Events;
4075 if (ar != null) {
4076 for (int i = 0; i < ar.Count; ++i) {
4077 Event ev = (Event) ar [i];
4078 if (ev.AreAccessorsDuplicateImplementation (this))
4079 return false;
4083 return true;
4087 // Creates the type
4089 public override bool Define ()
4091 if (!base.Define ())
4092 return false;
4094 if (RootContext.StdLib && (ReturnType == TypeManager.arg_iterator_type || ReturnType == TypeManager.typed_reference_type)) {
4095 Error1599 (Location, ReturnType);
4096 return false;
4099 if (ReturnType == TypeManager.void_type && ParameterTypes.Length == 0 &&
4100 Name == "Finalize" && !(this is Destructor)) {
4101 Report.Warning (465, 1, Location, "Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4105 // Setup iterator if we are one
4107 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4108 Iterator iterator = new Iterator (
4109 this, Parent, GenericMethod, ModFlags);
4111 if (!iterator.DefineIterator ())
4112 return false;
4116 // This is used to track the Entry Point,
4118 if (Name == "Main" &&
4119 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
4120 (RootContext.MainClass == null ||
4121 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4122 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
4123 IMethodData md = TypeManager.GetMethod (MethodBuilder);
4124 md.SetMemberIsUsed ();
4126 if (RootContext.EntryPoint == null) {
4127 if (Parent.IsGeneric){
4128 Report.Error (-201, Location,
4129 "Entry point can not be defined in a generic class");
4132 RootContext.EntryPoint = MethodBuilder;
4133 RootContext.EntryPointLocation = Location;
4134 } else {
4135 Error_DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
4136 Error_DuplicateEntryPoint (MethodBuilder, Location);
4138 } else {
4139 if (RootContext.WarningLevel >= 4)
4140 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder));
4144 return true;
4148 // Emits the code
4150 public override void Emit ()
4152 MethodData.Emit (Parent);
4153 base.Emit ();
4155 Block = null;
4156 MethodData = null;
4159 public static void Error1599 (Location loc, Type t)
4161 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4164 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4166 MethodInfo mi = (MethodInfo) ParentContainer.BaseCache.FindMemberToOverride (
4167 Parent.TypeBuilder, Name, ParameterTypes, GenericMethod, false);
4169 if (mi == null)
4170 return null;
4172 base_ret_type = mi.ReturnType;
4173 return mi;
4176 protected override bool VerifyClsCompliance ()
4178 if (!base.VerifyClsCompliance ())
4179 return false;
4181 if (ParameterInfo.Count > 0) {
4182 ArrayList al = (ArrayList)ParentContainer.MemberCache.Members [Name];
4183 if (al.Count > 1)
4184 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4187 return true;
4191 public abstract class ConstructorInitializer {
4192 ArrayList argument_list;
4193 protected ConstructorInfo base_constructor;
4194 Location loc;
4196 public ConstructorInitializer (ArrayList argument_list, Location loc)
4198 this.argument_list = argument_list;
4199 this.loc = loc;
4202 public ArrayList Arguments {
4203 get {
4204 return argument_list;
4208 public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
4210 Expression base_constructor_group;
4211 Type t;
4212 bool error = false;
4214 ec.CurrentBlock = block;
4216 if (argument_list != null){
4217 foreach (Argument a in argument_list){
4218 if (!a.Resolve (ec, loc))
4219 return false;
4222 ec.CurrentBlock = null;
4224 if (this is ConstructorBaseInitializer) {
4225 if (ec.ContainerType.BaseType == null)
4226 return true;
4228 t = ec.ContainerType.BaseType;
4229 if (ec.ContainerType.IsValueType) {
4230 Report.Error (522, loc,
4231 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4232 return false;
4234 } else
4235 t = ec.ContainerType;
4237 base_constructor_group = Expression.MemberLookup (
4238 ec.ContainerType, t, ".ctor", MemberTypes.Constructor,
4239 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4240 loc);
4242 if (base_constructor_group == null){
4243 error = true;
4244 base_constructor_group = Expression.MemberLookup (
4245 t, null, t, ".ctor", MemberTypes.Constructor,
4246 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4247 loc);
4250 int errors = Report.Errors;
4251 if (base_constructor_group != null)
4252 base_constructor = (ConstructorInfo) Invocation.OverloadResolve (
4253 ec, (MethodGroupExpr) base_constructor_group, argument_list,
4254 false, loc);
4256 if (base_constructor == null) {
4257 if (errors == Report.Errors)
4258 Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
4259 argument_list == null ? 0 : argument_list.Count);
4260 return false;
4263 if (error) {
4264 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
4265 base_constructor = null;
4266 return false;
4269 if (base_constructor == caller_builder){
4270 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4271 return false;
4274 return true;
4277 public virtual void Emit (EmitContext ec)
4279 if (base_constructor != null){
4280 ec.Mark (loc, false);
4281 if (ec.IsStatic)
4282 Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4283 else
4284 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4289 public class ConstructorBaseInitializer : ConstructorInitializer {
4290 public ConstructorBaseInitializer (ArrayList argument_list, Location l) :
4291 base (argument_list, l)
4296 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4297 public GeneratedBaseInitializer (Location loc):
4298 base (null, loc)
4303 public class ConstructorThisInitializer : ConstructorInitializer {
4304 public ConstructorThisInitializer (ArrayList argument_list, Location l) :
4305 base (argument_list, l)
4310 public class Constructor : MethodCore, IMethodData {
4311 public ConstructorBuilder ConstructorBuilder;
4312 public ConstructorInitializer Initializer;
4313 ListDictionary declarative_security;
4315 // <summary>
4316 // Modifiers allowed for a constructor.
4317 // </summary>
4318 public const int AllowedModifiers =
4319 Modifiers.PUBLIC |
4320 Modifiers.PROTECTED |
4321 Modifiers.INTERNAL |
4322 Modifiers.STATIC |
4323 Modifiers.UNSAFE |
4324 Modifiers.EXTERN |
4325 Modifiers.PRIVATE;
4327 static string[] attribute_targets = new string [] { "method" };
4329 bool has_compliant_args = false;
4331 // The spec claims that static is not permitted, but
4332 // my very own code has static constructors.
4334 public Constructor (DeclSpace parent, string name, int mod, Parameters args,
4335 ConstructorInitializer init, Location loc)
4336 : base (parent, null, null, mod, AllowedModifiers, false,
4337 new MemberName (name, loc), null, args)
4339 Initializer = init;
4342 public bool HasCompliantArgs {
4343 get { return has_compliant_args; }
4346 public override AttributeTargets AttributeTargets {
4347 get { return AttributeTargets.Constructor; }
4352 // Returns true if this is a default constructor
4354 public bool IsDefault ()
4356 if ((ModFlags & Modifiers.STATIC) != 0)
4357 return Parameters.Empty;
4359 return Parameters.Empty &&
4360 (Initializer is ConstructorBaseInitializer) &&
4361 (Initializer.Arguments == null);
4364 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4366 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4367 if (declarative_security == null) {
4368 declarative_security = new ListDictionary ();
4370 a.ExtractSecurityPermissionSet (declarative_security);
4371 return;
4374 if (a.Type == TypeManager.methodimpl_attr_type &&
4375 (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
4376 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
4379 ConstructorBuilder.SetCustomAttribute (cb);
4382 protected override bool CheckForDuplications ()
4384 ArrayList ar = ParentContainer.InstanceConstructors;
4385 if (ar != null) {
4386 int arLen = ar.Count;
4388 for (int i = 0; i < arLen; i++) {
4389 Constructor m = (Constructor) ar [i];
4390 if (IsDuplicateImplementation (m))
4391 return false;
4394 return true;
4397 protected override bool CheckBase ()
4399 if ((ModFlags & Modifiers.STATIC) != 0) {
4400 if (!Parameters.Empty) {
4401 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4402 GetSignatureForError ());
4403 return false;
4406 // the rest can be ignored
4407 return true;
4410 // Check whether arguments were correct.
4411 if (!DoDefineParameters ())
4412 return false;
4414 if (!CheckForDuplications ())
4415 return false;
4417 if (ParentContainer.Kind == Kind.Struct) {
4418 if (ParameterTypes.Length == 0) {
4419 Report.Error (568, Location,
4420 "Structs cannot contain explicit parameterless constructors");
4421 return false;
4424 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4425 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4426 return false;
4430 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4431 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4434 return true;
4438 // Creates the ConstructorBuilder
4440 public override bool Define ()
4442 if (ConstructorBuilder != null)
4443 return true;
4445 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4446 MethodAttributes.SpecialName);
4448 if ((ModFlags & Modifiers.STATIC) != 0){
4449 ca |= MethodAttributes.Static | MethodAttributes.Private;
4450 } else {
4451 ca |= MethodAttributes.HideBySig;
4453 if ((ModFlags & Modifiers.PUBLIC) != 0)
4454 ca |= MethodAttributes.Public;
4455 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4456 if ((ModFlags & Modifiers.INTERNAL) != 0)
4457 ca |= MethodAttributes.FamORAssem;
4458 else
4459 ca |= MethodAttributes.Family;
4460 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4461 ca |= MethodAttributes.Assembly;
4462 else
4463 ca |= MethodAttributes.Private;
4466 if (!CheckAbstractAndExtern (block != null))
4467 return false;
4469 // Check if arguments were correct.
4470 if (!CheckBase ())
4471 return false;
4473 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4474 ca, CallingConventions,
4475 ParameterTypes);
4477 if ((ModFlags & Modifiers.UNSAFE) != 0)
4478 ConstructorBuilder.InitLocals = false;
4480 if (ParentContainer.IsComImport) {
4481 if (!IsDefault ()) {
4482 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4483 Parent.GetSignatureForError ());
4484 return false;
4486 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4489 TypeManager.AddMethod (ConstructorBuilder, this);
4491 return true;
4495 // Emits the code
4497 public override void Emit ()
4499 if (OptAttributes != null)
4500 OptAttributes.Emit ();
4502 EmitContext ec = CreateEmitContext (null, null);
4504 if (block != null) {
4505 // If this is a non-static `struct' constructor and doesn't have any
4506 // initializer, it must initialize all of the struct's fields.
4507 if ((ParentContainer.Kind == Kind.Struct) &&
4508 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4509 block.AddThisVariable (Parent, Location);
4511 if (!block.ResolveMeta (ec, ParameterInfo))
4512 block = null;
4515 if ((ModFlags & Modifiers.STATIC) == 0){
4516 if (ParentContainer.Kind == Kind.Class && Initializer == null)
4517 Initializer = new GeneratedBaseInitializer (Location);
4521 // Spec mandates that Initializers will not have
4522 // `this' access
4524 ec.IsStatic = true;
4525 if ((Initializer != null) &&
4526 !Initializer.Resolve (ConstructorBuilder, block, ec))
4527 return;
4528 ec.IsStatic = false;
4531 Parameters.ApplyAttributes (ConstructorBuilder);
4533 SourceMethod source = SourceMethod.Create (
4534 Parent, ConstructorBuilder, block);
4537 // Classes can have base initializers and instance field initializers.
4539 if (ParentContainer.Kind == Kind.Class){
4540 if ((ModFlags & Modifiers.STATIC) == 0){
4543 // If we use a "this (...)" constructor initializer, then
4544 // do not emit field initializers, they are initialized in the other constructor
4546 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4547 ParentContainer.EmitFieldInitializers (ec);
4550 if (Initializer != null) {
4551 Initializer.Emit (ec);
4554 if ((ModFlags & Modifiers.STATIC) != 0)
4555 ParentContainer.EmitFieldInitializers (ec);
4557 ec.EmitTopBlock (this, block);
4559 if (source != null)
4560 source.CloseMethod ();
4562 base.Emit ();
4564 if (declarative_security != null) {
4565 foreach (DictionaryEntry de in declarative_security) {
4566 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4570 block = null;
4573 // Is never override
4574 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4576 return null;
4579 public override string GetSignatureForError()
4581 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4584 public override string[] ValidAttributeTargets {
4585 get {
4586 return attribute_targets;
4590 protected override bool VerifyClsCompliance ()
4592 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
4593 return false;
4596 if (ParameterInfo.Count > 0) {
4597 ArrayList al = (ArrayList)Parent.MemberCache.Members [".ctor"];
4598 if (al.Count > 3)
4599 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4601 if (Parent.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4602 foreach (Type param in ParameterTypes) {
4603 if (param.IsArray) {
4604 return true;
4609 has_compliant_args = true;
4610 return true;
4613 #region IMethodData Members
4615 public System.Reflection.CallingConventions CallingConventions {
4616 get {
4617 CallingConventions cc = Parameters.CallingConvention;
4619 if (ParentContainer.Kind == Kind.Class)
4620 if ((ModFlags & Modifiers.STATIC) == 0)
4621 cc |= CallingConventions.HasThis;
4623 // FIXME: How is `ExplicitThis' used in C#?
4625 return cc;
4629 public new Location Location {
4630 get {
4631 return base.Location;
4635 public MemberName MethodName {
4636 get {
4637 return MemberName;
4641 public Type ReturnType {
4642 get {
4643 return MemberType;
4647 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
4649 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4650 return new EmitContext (this, Parent, Location, ig_, null, ModFlags, true);
4653 public bool IsExcluded()
4655 return false;
4658 GenericMethod IMethodData.GenericMethod {
4659 get {
4660 return null;
4664 #endregion
4667 /// <summary>
4668 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4669 /// </summary>
4670 public interface IMethodData
4672 CallingConventions CallingConventions { get; }
4673 Location Location { get; }
4674 MemberName MethodName { get; }
4675 Type ReturnType { get; }
4676 GenericMethod GenericMethod { get; }
4677 Parameters ParameterInfo { get; }
4679 Attributes OptAttributes { get; }
4680 ToplevelBlock Block { get; set; }
4682 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
4683 ObsoleteAttribute GetObsoleteAttribute ();
4684 string GetSignatureForError ();
4685 bool IsExcluded ();
4686 bool IsClsComplianceRequired ();
4687 void SetMemberIsUsed ();
4691 // Encapsulates most of the Method's state
4693 public class MethodData {
4695 readonly IMethodData method;
4697 public readonly GenericMethod GenericMethod;
4700 // Are we implementing an interface ?
4702 public MethodInfo implementing;
4705 // Protected data.
4707 protected MemberBase member;
4708 protected int modifiers;
4709 protected MethodAttributes flags;
4710 protected Type declaring_type;
4711 protected MethodInfo parent_method;
4713 MethodBuilder builder = null;
4714 public MethodBuilder MethodBuilder {
4715 get {
4716 return builder;
4720 public Type DeclaringType {
4721 get {
4722 return declaring_type;
4726 public MethodData (MemberBase member,
4727 int modifiers, MethodAttributes flags, IMethodData method)
4729 this.member = member;
4730 this.modifiers = modifiers;
4731 this.flags = flags;
4733 this.method = method;
4736 public MethodData (MemberBase member,
4737 int modifiers, MethodAttributes flags,
4738 IMethodData method, MethodBuilder builder,
4739 GenericMethod generic, MethodInfo parent_method)
4740 : this (member, modifiers, flags, method)
4742 this.builder = builder;
4743 this.GenericMethod = generic;
4744 this.parent_method = parent_method;
4747 public bool Define (DeclSpace parent)
4749 string name = method.MethodName.Basename;
4750 string method_name = method.MethodName.FullName;
4752 TypeContainer container = ((TypeContainer) parent).PartialContainer;
4754 PendingImplementation pending = container.PendingImplementations;
4755 if (pending != null){
4756 if (member is Indexer) // TODO: test it, but it should work without this IF
4757 implementing = pending.IsInterfaceIndexer (
4758 member.InterfaceType, method.ReturnType, method.ParameterInfo);
4759 else
4760 implementing = pending.IsInterfaceMethod (
4761 member.InterfaceType, name, method.ReturnType, method.ParameterInfo);
4763 if (member.InterfaceType != null){
4764 if (implementing == null){
4765 if (member is PropertyBase) {
4766 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
4767 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
4768 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
4770 } else {
4771 Report.Error (539, method.Location,
4772 "`{0}.{1}' in explicit interface declaration is not a member of interface",
4773 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
4775 return false;
4777 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
4778 Report.SymbolRelatedToPreviousError (implementing);
4779 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
4780 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
4781 return false;
4784 method_name = TypeManager.GetFullName (member.InterfaceType) +
4785 '.' + method_name;
4786 } else {
4787 if (implementing != null) {
4788 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
4789 if (prop_method != null) {
4790 if (!implementing.IsSpecialName) {
4791 Report.SymbolRelatedToPreviousError (implementing);
4792 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
4793 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
4794 return false;
4796 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
4797 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
4798 Report.SymbolRelatedToPreviousError (implementing);
4799 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
4800 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
4801 return false;
4809 // For implicit implementations, make sure we are public, for
4810 // explicit implementations, make sure we are private.
4812 if (implementing != null){
4814 // Setting null inside this block will trigger a more
4815 // verbose error reporting for missing interface implementations
4817 // The "candidate" function has been flagged already
4818 // but it wont get cleared
4820 if (member.IsExplicitImpl){
4821 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4822 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4823 implementing = null;
4825 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4826 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4828 // If this is an interface method implementation,
4829 // check for public accessibility
4831 implementing = null;
4832 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4833 // We may never be private.
4834 implementing = null;
4835 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4837 // We may be protected if we're overriding something.
4839 implementing = null;
4844 // Static is not allowed
4846 if ((modifiers & Modifiers.STATIC) != 0){
4847 implementing = null;
4852 // If implementing is still valid, set flags
4854 if (implementing != null){
4856 // When implementing interface methods, set NewSlot
4857 // unless, we are overwriting a method.
4859 if (implementing.DeclaringType.IsInterface){
4860 if ((modifiers & Modifiers.OVERRIDE) == 0)
4861 flags |= MethodAttributes.NewSlot;
4863 flags |=
4864 MethodAttributes.Virtual |
4865 MethodAttributes.HideBySig;
4867 // Set Final unless we're virtual, abstract or already overriding a method.
4868 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4869 flags |= MethodAttributes.Final;
4872 EmitContext ec = method.CreateEmitContext (container, null);
4874 DefineMethodBuilder (container, method_name, method.ParameterInfo.Types);
4876 if (builder == null)
4877 return false;
4879 if (container.CurrentType != null)
4880 declaring_type = container.CurrentType;
4881 else
4882 declaring_type = container.TypeBuilder;
4884 if ((modifiers & Modifiers.UNSAFE) != 0)
4885 builder.InitLocals = false;
4887 if (implementing != null){
4889 // clear the pending implemntation flag
4891 if (member is Indexer) {
4892 pending.ImplementIndexer (
4893 member.InterfaceType, builder, method.ReturnType,
4894 method.ParameterInfo, member.IsExplicitImpl);
4895 } else
4896 pending.ImplementMethod (
4897 member.InterfaceType, name, method.ReturnType,
4898 method.ParameterInfo, member.IsExplicitImpl);
4900 if (member.IsExplicitImpl)
4901 container.TypeBuilder.DefineMethodOverride (
4902 builder, implementing);
4906 TypeManager.AddMethod (builder, method);
4908 if (GenericMethod != null) {
4909 bool is_override = member.IsExplicitImpl |
4910 ((modifiers & Modifiers.OVERRIDE) != 0);
4912 if (implementing != null)
4913 parent_method = implementing;
4915 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
4916 return false;
4919 return true;
4923 /// <summary>
4924 /// Create the MethodBuilder for the method
4925 /// </summary>
4926 void DefineMethodBuilder (TypeContainer container, string method_name, Type[] ParameterTypes)
4928 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4930 if ((modifiers & extern_static) == extern_static) {
4932 if (method.OptAttributes != null) {
4933 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type);
4934 if (dllimport_attribute != null) {
4935 flags |= MethodAttributes.PinvokeImpl;
4936 builder = dllimport_attribute.DefinePInvokeMethod (
4937 container.TypeBuilder, method_name, flags,
4938 method.ReturnType, ParameterTypes);
4940 return;
4944 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4945 // We are more strict than Microsoft and report CS0626 like error
4946 if (method.OptAttributes == null ||
4947 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type)) {
4948 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",
4949 method.GetSignatureForError ());
4950 return;
4954 if (builder == null) {
4955 builder = container.TypeBuilder.DefineMethod (
4956 method_name, flags, method.CallingConventions,
4957 method.ReturnType, ParameterTypes);
4958 return;
4960 #if !MS_COMPATIBLE
4961 builder.SetGenericMethodSignature (
4962 flags, method.CallingConventions,
4963 method.ReturnType, ParameterTypes);
4964 #endif
4968 // Emits the code
4970 public void Emit (DeclSpace parent)
4972 EmitContext ec;
4973 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4974 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
4975 else
4976 ec = method.CreateEmitContext (parent, null);
4978 method.ParameterInfo.ApplyAttributes (MethodBuilder);
4980 if (GenericMethod != null)
4981 GenericMethod.EmitAttributes ();
4983 ToplevelBlock block = method.Block;
4985 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
4988 // Handle destructors specially
4990 // FIXME: This code generates buggy code
4992 if (member is Destructor)
4993 EmitDestructor (ec, block);
4994 else
4995 ec.EmitTopBlock (method, block);
4997 if (source != null)
4998 source.CloseMethod ();
5001 void EmitDestructor (EmitContext ec, ToplevelBlock block)
5003 ILGenerator ig = ec.ig;
5005 Label finish = ig.DefineLabel ();
5007 block.SetDestructor ();
5009 ig.BeginExceptionBlock ();
5010 ec.ReturnLabel = finish;
5011 ec.HasReturnLabel = true;
5012 ec.EmitTopBlock (method, block);
5014 // ig.MarkLabel (finish);
5015 ig.BeginFinallyBlock ();
5017 if (ec.ContainerType.BaseType != null) {
5018 Expression member_lookup = Expression.MemberLookup (
5019 ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
5020 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
5022 if (member_lookup != null){
5023 MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
5025 ig.Emit (OpCodes.Ldarg_0);
5026 ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
5030 ig.EndExceptionBlock ();
5031 //ig.MarkLabel (ec.ReturnLabel);
5032 ig.Emit (OpCodes.Ret);
5036 // TODO: Should derive from MethodCore
5037 public class Destructor : Method {
5039 static string[] attribute_targets = new string [] { "method" };
5041 public Destructor (DeclSpace parent, Expression return_type, int mod,
5042 string name, Parameters parameters, Attributes attrs,
5043 Location l)
5044 : base (parent, null, return_type, mod, false, new MemberName (name, l),
5045 parameters, attrs)
5048 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5050 if (a.Type == TypeManager.conditional_attribute_type) {
5051 Error_ConditionalAttributeIsNotValid ();
5052 return;
5055 base.ApplyAttributeBuilder (a, cb);
5058 public override string GetSignatureForError ()
5060 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5063 public override string[] ValidAttributeTargets {
5064 get {
5065 return attribute_targets;
5070 abstract public class MemberBase : MemberCore {
5071 public Expression Type;
5073 public MethodAttributes flags;
5074 public readonly DeclSpace ds;
5075 public readonly GenericMethod GenericMethod;
5077 protected readonly int explicit_mod_flags;
5080 // The "short" name of this property / indexer / event. This is the
5081 // name without the explicit interface.
5083 public string ShortName {
5084 get { return MemberName.Name; }
5085 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
5088 public TypeContainer ParentContainer {
5089 get { return ((TypeContainer) Parent).PartialContainer; }
5093 // The type of this property / indexer / event
5095 protected Type member_type;
5096 public Type MemberType {
5097 get {
5098 if (member_type == null && Type != null) {
5099 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
5100 Type = Type.ResolveAsTypeTerminal (rc, false);
5101 if (Type != null) {
5102 member_type = Type.Type;
5105 return member_type;
5110 // Whether this is an interface member.
5112 public bool IsInterface;
5115 // If true, this is an explicit interface implementation
5117 public bool IsExplicitImpl;
5120 // The interface type we are explicitly implementing
5122 public Type InterfaceType = null;
5125 // The constructor is only exposed to our children
5127 protected MemberBase (DeclSpace parent, GenericMethod generic,
5128 Expression type, int mod, int allowed_mod, int def_mod,
5129 MemberName name, Attributes attrs)
5130 : base (parent, name, attrs)
5132 this.ds = generic != null ? generic : (DeclSpace) parent;
5133 explicit_mod_flags = mod;
5134 Type = type;
5135 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
5136 IsExplicitImpl = (MemberName.Left != null);
5137 GenericMethod = generic;
5138 if (GenericMethod != null)
5139 GenericMethod.ModFlags = ModFlags;
5142 protected virtual bool CheckBase ()
5144 if ((ModFlags & Modifiers.PROTECTED) != 0 && ParentContainer.Kind == Kind.Struct) {
5145 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
5146 return false;
5149 if ((RootContext.WarningLevel >= 4) &&
5150 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
5151 ((ModFlags & Modifiers.PROTECTED) != 0) &&
5152 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
5153 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
5155 return true;
5158 protected virtual bool DoDefineBase ()
5160 if (Name == null)
5161 throw new InternalErrorException ();
5163 if (IsInterface) {
5164 ModFlags = Modifiers.PUBLIC |
5165 Modifiers.ABSTRACT |
5166 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
5168 flags = MethodAttributes.Public |
5169 MethodAttributes.Abstract |
5170 MethodAttributes.HideBySig |
5171 MethodAttributes.NewSlot |
5172 MethodAttributes.Virtual;
5173 } else {
5174 if (!ParentContainer.MethodModifiersValid (this))
5175 return false;
5177 flags = Modifiers.MethodAttr (ModFlags);
5180 if (IsExplicitImpl) {
5181 Expression expr = MemberName.Left.GetTypeExpression ();
5182 TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (this, false);
5183 if (iface_texpr == null)
5184 return false;
5186 InterfaceType = iface_texpr.Type;
5188 if (!InterfaceType.IsInterface) {
5189 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
5190 return false;
5193 if (!ParentContainer.VerifyImplements (this))
5194 return false;
5196 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5199 return true;
5202 protected virtual bool DoDefine ()
5204 if (MemberType == null)
5205 return false;
5207 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5208 (ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0) {
5209 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5210 GetSignatureForError (), Parent.GetSignatureForError ());
5211 return false;
5214 // verify accessibility
5215 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5216 Report.SymbolRelatedToPreviousError (MemberType);
5217 if (this is Property)
5218 Report.Error (53, Location,
5219 "Inconsistent accessibility: property type `" +
5220 TypeManager.CSharpName (MemberType) + "' is less " +
5221 "accessible than property `" + GetSignatureForError () + "'");
5222 else if (this is Indexer)
5223 Report.Error (54, Location,
5224 "Inconsistent accessibility: indexer return type `" +
5225 TypeManager.CSharpName (MemberType) + "' is less " +
5226 "accessible than indexer `" + GetSignatureForError () + "'");
5227 else if (this is MethodCore) {
5228 if (this is Operator)
5229 Report.Error (56, Location,
5230 "Inconsistent accessibility: return type `" +
5231 TypeManager.CSharpName (MemberType) + "' is less " +
5232 "accessible than operator `" + GetSignatureForError () + "'");
5233 else
5234 Report.Error (50, Location,
5235 "Inconsistent accessibility: return type `" +
5236 TypeManager.CSharpName (MemberType) + "' is less " +
5237 "accessible than method `" + GetSignatureForError () + "'");
5238 } else {
5239 Report.Error (52, Location,
5240 "Inconsistent accessibility: field type `" +
5241 TypeManager.CSharpName (MemberType) + "' is less " +
5242 "accessible than field `" + GetSignatureForError () + "'");
5244 return false;
5247 if (IsExplicitImpl) {
5248 Expression expr = MemberName.Left.GetTypeExpression ();
5249 TypeExpr texpr = expr.ResolveAsTypeTerminal (this, false);
5250 if (texpr == null)
5251 return false;
5253 InterfaceType = texpr.Type;
5255 if (!InterfaceType.IsInterface) {
5256 Report.Error (538, Location, "`{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
5257 return false;
5260 if (!ParentContainer.VerifyImplements (this))
5261 return false;
5263 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5266 return true;
5269 protected bool IsTypePermitted ()
5271 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5272 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5273 return false;
5275 return true;
5278 protected override bool VerifyClsCompliance()
5280 if (base.VerifyClsCompliance ()) {
5281 return true;
5284 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
5285 Report.Error (3010, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
5287 return false;
5293 // Fields and Events both generate FieldBuilders, we use this to share
5294 // their common bits. This is also used to flag usage of the field
5296 abstract public class FieldBase : MemberBase {
5297 public FieldBuilder FieldBuilder;
5298 public Status status;
5299 protected Expression initializer;
5300 ExpressionStatement initializerStatement;
5302 [Flags]
5303 public enum Status : byte {
5304 HAS_OFFSET = 4 // Used by FieldMember.
5307 static string[] attribute_targets = new string [] { "field" };
5309 /// <summary>
5310 /// Symbol with same name in base class/struct
5311 /// </summary>
5312 public MemberInfo conflict_symbol;
5314 protected FieldBase (DeclSpace parent, Expression type, int mod,
5315 int allowed_mod, MemberName name, Attributes attrs)
5316 : base (parent, null, type, mod, allowed_mod, Modifiers.PRIVATE,
5317 name, attrs)
5321 public override AttributeTargets AttributeTargets {
5322 get {
5323 return AttributeTargets.Field;
5327 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5329 if (a.Type == TypeManager.marshal_as_attr_type) {
5330 UnmanagedMarshal marshal = a.GetMarshal (this);
5331 if (marshal != null) {
5332 FieldBuilder.SetMarshal (marshal);
5334 return;
5337 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5338 a.Error_InvalidSecurityParent ();
5339 return;
5342 FieldBuilder.SetCustomAttribute (cb);
5345 public void EmitInitializer (EmitContext ec)
5347 initializerStatement.EmitStatement (ec);
5350 protected override bool CheckBase ()
5352 if (!base.CheckBase ())
5353 return false;
5355 // TODO: Implement
5356 if (IsInterface)
5357 return true;
5359 conflict_symbol = ParentContainer.FindBaseMemberWithSameName (Name, false);
5360 if (conflict_symbol == null) {
5361 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5362 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5364 return true;
5367 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5368 Report.SymbolRelatedToPreviousError (conflict_symbol);
5369 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5370 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5373 return true;
5376 public Expression Initializer {
5377 set {
5378 if (value != null) {
5379 this.initializer = value;
5380 ParentContainer.RegisterFieldForInitialization (this);
5385 protected virtual bool IsFieldClsCompliant {
5386 get {
5387 if (FieldBuilder == null)
5388 return true;
5390 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5394 public Expression ResolveInitializer ()
5396 // TODO: again it's too heavy-weight
5397 EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5398 ec.IsFieldInitializer = true;
5399 initializer = initializer.Resolve (ec);
5400 if (initializer == null)
5401 return null;
5403 FieldExpr fe = new FieldExpr (FieldBuilder, Location, true);
5404 if ((ModFlags & Modifiers.STATIC) == 0)
5406 fe.InstanceExpression = CompilerGeneratedThis.Instance;
5409 initializerStatement = new Assign (fe, initializer, Location).ResolveStatement (ec);
5410 return initializer;
5413 public bool HasDefaultInitializer
5417 Constant c = initializer as Constant;
5418 if (c == null)
5419 return false;
5421 return c.IsDefaultInitializer (MemberType);
5425 public override string[] ValidAttributeTargets
5427 get {
5428 return attribute_targets;
5432 protected override bool VerifyClsCompliance ()
5434 if (!base.VerifyClsCompliance ())
5435 return false;
5437 if (!IsFieldClsCompliant) {
5438 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant", GetSignatureForError ());
5440 return true;
5444 public void SetAssigned ()
5446 caching_flags |= Flags.IsAssigned;
5450 public abstract class FieldMember : FieldBase
5452 protected FieldMember (DeclSpace parent, Expression type, int mod,
5453 int allowed_mod, MemberName name, Attributes attrs)
5454 : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, attrs)
5456 if ((mod & Modifiers.ABSTRACT) != 0)
5457 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5460 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5462 if (a.Type == TypeManager.field_offset_attribute_type)
5464 status |= Status.HAS_OFFSET;
5466 if (!ParentContainer.HasExplicitLayout) {
5467 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5468 return;
5471 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5472 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5473 return;
5477 if (a.Type == TypeManager.fixed_buffer_attr_type) {
5478 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5479 return;
5482 base.ApplyAttributeBuilder (a, cb);
5485 public override bool Define()
5487 if (MemberType == null || Type == null)
5488 return false;
5490 if (MemberType == TypeManager.void_type) {
5491 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5492 return false;
5495 if (!CheckBase ())
5496 return false;
5498 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5499 Report.Error (52, Location,
5500 "Inconsistent accessibility: field type `" +
5501 TypeManager.CSharpName (MemberType) + "' is less " +
5502 "accessible than field `" + GetSignatureForError () + "'");
5503 return false;
5506 if (!IsTypePermitted ())
5507 return false;
5509 return true;
5512 public override void Emit ()
5514 if (OptAttributes != null) {
5515 OptAttributes.Emit ();
5518 if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0 && ParentContainer.HasExplicitLayout) {
5519 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5522 base.Emit ();
5526 // Represents header string for documentation comment.
5528 public override string DocCommentHeader {
5529 get { return "F:"; }
5533 interface IFixedBuffer
5535 FieldInfo Element { get; }
5536 Type ElementType { get; }
5539 public class FixedFieldExternal: IFixedBuffer
5541 FieldInfo element_field;
5543 public FixedFieldExternal (FieldInfo fi)
5545 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5548 #region IFixedField Members
5550 public FieldInfo Element {
5551 get {
5552 return element_field;
5556 public Type ElementType {
5557 get {
5558 return element_field.FieldType;
5562 #endregion
5565 /// <summary>
5566 /// Fixed buffer implementation
5567 /// </summary>
5568 public class FixedField : FieldMember, IFixedBuffer
5570 public const string FixedElementName = "FixedElementField";
5571 static int GlobalCounter = 0;
5572 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5573 static FieldInfo[] fi;
5575 TypeBuilder fixed_buffer_type;
5576 FieldBuilder element;
5577 Expression size_expr;
5578 int buffer_size;
5580 const int AllowedModifiers =
5581 Modifiers.NEW |
5582 Modifiers.PUBLIC |
5583 Modifiers.PROTECTED |
5584 Modifiers.INTERNAL |
5585 Modifiers.PRIVATE;
5587 public FixedField (DeclSpace parent, Expression type, int mod, string name,
5588 Expression size_expr, Attributes attrs, Location loc):
5589 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5591 if (RootContext.Version == LanguageVersion.ISO_1)
5592 Report.FeatureIsNotStandardized (loc, "fixed size buffers");
5594 this.size_expr = size_expr;
5597 public override bool Define()
5599 #if !NET_2_0
5600 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5601 Report.Warning (-23, 1, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5602 #endif
5604 if (ParentContainer.Kind != Kind.Struct) {
5605 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5606 GetSignatureForError ());
5607 return false;
5610 if (!base.Define ())
5611 return false;
5613 if (!TypeManager.IsPrimitiveType (MemberType)) {
5614 Report.Error (1663, Location, "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double",
5615 GetSignatureForError ());
5616 return false;
5619 EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5620 Constant c = size_expr.ResolveAsConstant (ec, this);
5621 if (c == null)
5622 return false;
5624 IntConstant buffer_size_const = c.ToInt (Location);
5625 if (buffer_size_const == null)
5626 return false;
5628 buffer_size = buffer_size_const.Value;
5630 if (buffer_size <= 0) {
5631 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5632 return false;
5635 int type_size = Expression.GetTypeSize (MemberType);
5637 if (buffer_size > int.MaxValue / type_size) {
5638 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5639 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5640 return false;
5643 buffer_size *= type_size;
5645 // Define nested
5646 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5648 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5649 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5650 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5651 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5653 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5654 TypeManager.RegisterFieldBase (FieldBuilder, this);
5656 return true;
5659 public override void Emit()
5661 if (fi == null)
5662 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5664 object[] fi_val = new object[1];
5665 fi_val [0] = buffer_size;
5667 CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor,
5668 ctor_args, fi, fi_val);
5669 fixed_buffer_type.SetCustomAttribute (cab);
5671 cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
5672 FieldBuilder.SetCustomAttribute (cab);
5673 base.Emit ();
5676 protected override bool IsFieldClsCompliant {
5677 get {
5678 return false;
5682 #region IFixedField Members
5684 public FieldInfo Element {
5685 get {
5686 return element;
5690 public Type ElementType {
5691 get {
5692 return MemberType;
5696 #endregion
5700 // The Field class is used to represents class/struct fields during parsing.
5702 public class Field : FieldMember {
5703 // <summary>
5704 // Modifiers allowed in a class declaration
5705 // </summary>
5706 const int AllowedModifiers =
5707 Modifiers.NEW |
5708 Modifiers.PUBLIC |
5709 Modifiers.PROTECTED |
5710 Modifiers.INTERNAL |
5711 Modifiers.PRIVATE |
5712 Modifiers.STATIC |
5713 Modifiers.VOLATILE |
5714 Modifiers.UNSAFE |
5715 Modifiers.READONLY;
5717 public Field (DeclSpace parent, Expression type, int mod, string name,
5718 Attributes attrs, Location loc)
5719 : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
5720 attrs)
5724 public override bool Define ()
5726 if (!base.Define ())
5727 return false;
5729 if (RootContext.WarningLevel > 1){
5730 Type ptype = Parent.TypeBuilder.BaseType;
5732 // ptype is only null for System.Object while compiling corlib.
5733 if (ptype != null){
5734 TypeContainer.FindMembers (
5735 ptype, MemberTypes.Method,
5736 BindingFlags.Public |
5737 BindingFlags.Static | BindingFlags.Instance,
5738 System.Type.FilterName, Name);
5742 if ((ModFlags & Modifiers.VOLATILE) != 0){
5743 if (!MemberType.IsClass){
5744 Type vt = MemberType;
5746 if (TypeManager.IsEnumType (vt))
5747 vt = TypeManager.EnumToUnderlying (MemberType);
5749 if (!((vt == TypeManager.bool_type) ||
5750 (vt == TypeManager.sbyte_type) ||
5751 (vt == TypeManager.byte_type) ||
5752 (vt == TypeManager.short_type) ||
5753 (vt == TypeManager.ushort_type) ||
5754 (vt == TypeManager.int32_type) ||
5755 (vt == TypeManager.uint32_type) ||
5756 (vt == TypeManager.char_type) ||
5757 (vt == TypeManager.float_type) ||
5758 (!vt.IsValueType))){
5759 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
5760 GetSignatureForError (), TypeManager.CSharpName (vt));
5761 return false;
5765 if ((ModFlags & Modifiers.READONLY) != 0){
5766 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
5767 GetSignatureForError ());
5768 return false;
5772 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5774 if (ParentContainer.Kind == Kind.Struct &&
5775 ((fa & FieldAttributes.Static) == 0) &&
5776 MemberType == Parent.TypeBuilder &&
5777 !TypeManager.IsBuiltinType (MemberType)){
5778 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
5779 "' causes a cycle in the structure layout");
5780 return false;
5783 try {
5784 FieldBuilder = Parent.TypeBuilder.DefineField (
5785 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5787 TypeManager.RegisterFieldBase (FieldBuilder, this);
5789 catch (ArgumentException) {
5790 Report.Warning (-24, 1, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5791 return false;
5794 return true;
5797 protected override bool VerifyClsCompliance ()
5799 if (!base.VerifyClsCompliance ())
5800 return false;
5802 if ((ModFlags & Modifiers.VOLATILE) != 0) {
5803 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
5806 return true;
5811 // `set' and `get' accessors are represented with an Accessor.
5813 public class Accessor : IIteratorContainer {
5815 // Null if the accessor is empty, or a Block if not
5817 public const int AllowedModifiers =
5818 Modifiers.PUBLIC |
5819 Modifiers.PROTECTED |
5820 Modifiers.INTERNAL |
5821 Modifiers.PRIVATE;
5823 public ToplevelBlock Block;
5824 public Attributes Attributes;
5825 public Location Location;
5826 public int ModFlags;
5827 public bool Yields;
5829 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5831 Block = b;
5832 Attributes = attrs;
5833 Location = loc;
5834 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5837 public void SetYields ()
5839 Yields = true;
5843 // Ooouh Martin, templates are missing here.
5844 // When it will be possible move here a lot of child code and template method type.
5845 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
5846 protected MethodData method_data;
5847 protected ToplevelBlock block;
5848 protected ListDictionary declarative_security;
5850 // The accessor are created event if they are not wanted.
5851 // But we need them because their names are reserved.
5852 // Field says whether accessor will be emited or not
5853 public readonly bool IsDummy;
5855 protected readonly string prefix;
5857 ReturnParameter return_attributes;
5859 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5860 : base (member.Parent, SetupName (prefix, member, member.Location), null)
5862 this.prefix = prefix;
5863 IsDummy = true;
5866 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5867 string prefix)
5868 : base (member.Parent, SetupName (prefix, member, accessor.Location),
5869 accessor.Attributes)
5871 this.prefix = prefix;
5872 this.block = accessor.Block;
5875 static MemberName SetupName (string prefix, MemberBase member, Location loc)
5877 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
5880 public void UpdateName (MemberBase member)
5882 SetMemberName (SetupName (prefix, member, Location));
5885 #region IMethodData Members
5887 public ToplevelBlock Block {
5888 get {
5889 return block;
5892 set {
5893 block = value;
5897 public CallingConventions CallingConventions {
5898 get {
5899 return CallingConventions.Standard;
5903 public bool IsExcluded ()
5905 return false;
5908 GenericMethod IMethodData.GenericMethod {
5909 get {
5910 return null;
5914 public MemberName MethodName {
5915 get {
5916 return MemberName;
5920 public Type[] ParameterTypes {
5921 get {
5922 return ParameterInfo.Types;
5926 public abstract Parameters ParameterInfo { get ; }
5927 public abstract Type ReturnType { get; }
5928 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
5930 #endregion
5932 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5934 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5935 a.Type == TypeManager.conditional_attribute_type) {
5936 Report.Error (1667, a.Location,
5937 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
5938 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5939 return;
5942 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
5943 if (declarative_security == null)
5944 declarative_security = new ListDictionary ();
5945 a.ExtractSecurityPermissionSet (declarative_security);
5946 return;
5949 if (a.Target == AttributeTargets.Method) {
5950 method_data.MethodBuilder.SetCustomAttribute (cb);
5951 return;
5954 if (a.Target == AttributeTargets.ReturnValue) {
5955 if (return_attributes == null)
5956 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5958 return_attributes.ApplyAttributeBuilder (a, cb);
5959 return;
5962 ApplyToExtraTarget (a, cb);
5965 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5967 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5970 public override bool Define()
5972 throw new NotSupportedException ();
5975 public void Emit (DeclSpace parent)
5977 EmitMethod (parent);
5979 if (OptAttributes != null)
5980 OptAttributes.Emit ();
5982 if (declarative_security != null) {
5983 foreach (DictionaryEntry de in declarative_security) {
5984 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5988 block = null;
5991 protected virtual void EmitMethod (DeclSpace parent)
5993 method_data.Emit (parent);
5996 public override bool IsClsComplianceRequired()
5998 return false;
6001 public bool IsDuplicateImplementation (MethodCore method)
6003 if (!MemberName.Equals (method.MemberName))
6004 return false;
6006 Type[] param_types = method.ParameterTypes;
6008 if (param_types.Length != ParameterTypes.Length)
6009 return false;
6011 for (int i = 0; i < param_types.Length; i++)
6012 if (param_types [i] != ParameterTypes [i])
6013 return false;
6015 Report.SymbolRelatedToPreviousError (method);
6016 Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
6017 return true;
6020 public override bool IsUsed
6022 get {
6023 if (IsDummy)
6024 return false;
6026 return base.IsUsed;
6030 public new Location Location {
6031 get {
6032 return base.Location;
6037 // Represents header string for documentation comment.
6039 public override string DocCommentHeader {
6040 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6046 // Properties and Indexers both generate PropertyBuilders, we use this to share
6047 // their common bits.
6049 abstract public class PropertyBase : MethodCore {
6051 public class GetMethod : PropertyMethod
6053 static string[] attribute_targets = new string [] { "method", "return" };
6055 public GetMethod (MethodCore method):
6056 base (method, "get_")
6060 public GetMethod (MethodCore method, Accessor accessor):
6061 base (method, accessor, "get_")
6065 public override MethodBuilder Define (DeclSpace parent)
6067 base.Define (parent);
6069 method_data = new MethodData (method, ModFlags, flags, this);
6071 if (!method_data.Define (parent))
6072 return null;
6074 return method_data.MethodBuilder;
6077 public override Type ReturnType {
6078 get {
6079 return method.MemberType;
6083 public override Parameters ParameterInfo {
6084 get {
6085 return Parameters.EmptyReadOnlyParameters;
6089 public override string[] ValidAttributeTargets {
6090 get {
6091 return attribute_targets;
6096 public class SetMethod : PropertyMethod {
6098 static string[] attribute_targets = new string [] { "method", "param", "return" };
6099 ImplicitParameter param_attr;
6100 protected Parameters parameters;
6102 public SetMethod (MethodCore method):
6103 base (method, "set_")
6107 public SetMethod (MethodCore method, Accessor accessor):
6108 base (method, accessor, "set_")
6112 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6114 if (a.Target == AttributeTargets.Parameter) {
6115 if (param_attr == null)
6116 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6118 param_attr.ApplyAttributeBuilder (a, cb);
6119 return;
6122 base.ApplyAttributeBuilder (a, cb);
6125 public override Parameters ParameterInfo {
6126 get {
6127 return parameters;
6131 protected virtual void DefineParameters ()
6133 parameters = new Parameters (
6134 new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
6135 new Type[] { method.MemberType });
6138 public override MethodBuilder Define (DeclSpace parent)
6140 DefineParameters ();
6141 if (IsDummy)
6142 return null;
6144 base.Define (parent);
6146 method_data = new MethodData (method, ModFlags, flags, this);
6148 if (!method_data.Define (parent))
6149 return null;
6151 return method_data.MethodBuilder;
6154 public override Type ReturnType {
6155 get {
6156 return TypeManager.void_type;
6160 public override string[] ValidAttributeTargets {
6161 get {
6162 return attribute_targets;
6167 static string[] attribute_targets = new string [] { "property" };
6169 public abstract class PropertyMethod : AbstractPropertyEventMethod
6171 protected readonly MethodCore method;
6172 protected MethodAttributes flags;
6173 bool yields;
6175 public PropertyMethod (MethodCore method, string prefix)
6176 : base (method, prefix)
6178 this.method = method;
6181 public PropertyMethod (MethodCore method, Accessor accessor,
6182 string prefix)
6183 : base (method, accessor, prefix)
6185 this.method = method;
6186 this.ModFlags = accessor.ModFlags;
6187 yields = accessor.Yields;
6189 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6190 Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
6194 public override AttributeTargets AttributeTargets {
6195 get {
6196 return AttributeTargets.Method;
6200 public override bool IsClsComplianceRequired ()
6202 return method.IsClsComplianceRequired ();
6205 public virtual MethodBuilder Define (DeclSpace parent)
6207 if (!method.CheckAbstractAndExtern (block != null))
6208 return null;
6210 TypeContainer container = ((TypeContainer) parent).PartialContainer;
6213 // Check for custom access modifier
6215 if (ModFlags == 0) {
6216 ModFlags = method.ModFlags;
6217 flags = method.flags;
6218 } else {
6219 if (container.Kind == Kind.Interface)
6220 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6221 GetSignatureForError ());
6223 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6224 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6227 CheckModifiers (ModFlags);
6228 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6229 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6230 flags = Modifiers.MethodAttr (ModFlags);
6231 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6235 // Setup iterator if we are one
6237 if (yields) {
6238 Iterator iterator = new Iterator (this, Parent as TypeContainer, null, ModFlags);
6240 if (!iterator.DefineIterator ())
6241 return null;
6244 return null;
6247 public bool HasCustomAccessModifier
6249 get {
6250 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6254 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6256 return new EmitContext (method,
6257 ds, method.ds, method.Location, ig, ReturnType,
6258 method.ModFlags, false);
6261 public override ObsoleteAttribute GetObsoleteAttribute ()
6263 return method.GetObsoleteAttribute ();
6266 public override string GetSignatureForError()
6268 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6271 void CheckModifiers (int modflags)
6273 int flags = 0;
6274 int mflags = method.ModFlags & Modifiers.Accessibility;
6276 if ((mflags & Modifiers.PUBLIC) != 0) {
6277 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6279 else if ((mflags & Modifiers.PROTECTED) != 0) {
6280 if ((mflags & Modifiers.INTERNAL) != 0)
6281 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6283 flags |= Modifiers.PRIVATE;
6285 else if ((mflags & Modifiers.INTERNAL) != 0)
6286 flags |= Modifiers.PRIVATE;
6288 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6289 Report.Error (273, Location,
6290 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6291 GetSignatureForError (), method.GetSignatureForError ());
6295 public override bool MarkForDuplicationCheck ()
6297 caching_flags |= Flags.TestMethodDuplication;
6298 return true;
6302 public PropertyMethod Get, Set;
6303 public PropertyBuilder PropertyBuilder;
6304 public MethodBuilder GetBuilder, SetBuilder;
6306 protected EmitContext ec;
6308 public PropertyBase (DeclSpace parent, Expression type, int mod_flags,
6309 int allowed_mod, bool is_iface, MemberName name,
6310 Parameters parameters, Attributes attrs)
6311 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name,
6312 attrs, parameters)
6316 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6318 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6319 a.Error_InvalidSecurityParent ();
6320 return;
6323 PropertyBuilder.SetCustomAttribute (cb);
6326 public override AttributeTargets AttributeTargets {
6327 get {
6328 return AttributeTargets.Property;
6332 public override bool Define ()
6334 if (!DoDefine ())
6335 return false;
6337 if (!IsTypePermitted ())
6338 return false;
6340 return true;
6343 protected override bool DoDefine ()
6345 if (!base.DoDefine ())
6346 return false;
6349 // Accessors modifiers check
6351 if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6352 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6353 GetSignatureForError ());
6354 return false;
6357 if ((Get.IsDummy || Set.IsDummy)
6358 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6359 Report.Error (276, Location,
6360 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6361 GetSignatureForError ());
6362 return false;
6365 if (MemberType.IsAbstract && MemberType.IsSealed) {
6366 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6367 return false;
6370 ec = new EmitContext (this, Parent, Location, null, MemberType, ModFlags);
6371 return true;
6374 protected override bool CheckForDuplications ()
6376 ArrayList ar = ParentContainer.Indexers;
6377 if (ar != null) {
6378 int arLen = ar.Count;
6380 for (int i = 0; i < arLen; i++) {
6381 Indexer m = (Indexer) ar [i];
6382 if (IsDuplicateImplementation (m))
6383 return false;
6387 ar = ParentContainer.Properties;
6388 if (ar != null) {
6389 int arLen = ar.Count;
6391 for (int i = 0; i < arLen; i++) {
6392 Property m = (Property) ar [i];
6393 if (IsDuplicateImplementation (m))
6394 return false;
6398 return true;
6401 // TODO: rename to Resolve......
6402 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6404 PropertyInfo base_property = ParentContainer.BaseCache.FindMemberToOverride (
6405 Parent.TypeBuilder, Name, ParameterTypes, null, true) as PropertyInfo;
6407 if (base_property == null)
6408 return null;
6410 base_ret_type = base_property.PropertyType;
6411 MethodInfo get_accessor = base_property.GetGetMethod (true);
6412 MethodInfo set_accessor = base_property.GetSetMethod (true);
6413 MethodAttributes get_accessor_access, set_accessor_access;
6415 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6416 if (Get != null && !Get.IsDummy && get_accessor == null) {
6417 Report.SymbolRelatedToPreviousError (base_property);
6418 Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6421 if (Set != null && !Set.IsDummy && set_accessor == null) {
6422 Report.SymbolRelatedToPreviousError (base_property);
6423 Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6428 // Check base class accessors access
6431 // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
6432 get_accessor_access = set_accessor_access = 0;
6433 if ((ModFlags & Modifiers.NEW) == 0) {
6434 if (get_accessor != null) {
6435 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6436 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6438 if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6439 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access, ".get");
6442 if (set_accessor != null) {
6443 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6444 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6446 if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6447 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6452 // Get the less restrictive access
6454 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6457 public override void Emit ()
6460 // The PropertyBuilder can be null for explicit implementations, in that
6461 // case, we do not actually emit the ".property", so there is nowhere to
6462 // put the attribute
6464 if (PropertyBuilder != null && OptAttributes != null)
6465 OptAttributes.Emit ();
6467 if (!Get.IsDummy)
6468 Get.Emit (Parent);
6470 if (!Set.IsDummy)
6471 Set.Emit (Parent);
6473 base.Emit ();
6476 /// <summary>
6477 /// Tests whether accessors are not in collision with some method (CS0111)
6478 /// </summary>
6479 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6481 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6484 public override bool IsUsed
6486 get {
6487 if (IsExplicitImpl)
6488 return true;
6490 return Get.IsUsed | Set.IsUsed;
6494 protected override void SetMemberName (MemberName new_name)
6496 base.SetMemberName (new_name);
6498 Get.UpdateName (this);
6499 Set.UpdateName (this);
6502 public override string[] ValidAttributeTargets {
6503 get {
6504 return attribute_targets;
6509 // Represents header string for documentation comment.
6511 public override string DocCommentHeader {
6512 get { return "P:"; }
6516 public class Property : PropertyBase {
6517 const int AllowedModifiers =
6518 Modifiers.NEW |
6519 Modifiers.PUBLIC |
6520 Modifiers.PROTECTED |
6521 Modifiers.INTERNAL |
6522 Modifiers.PRIVATE |
6523 Modifiers.STATIC |
6524 Modifiers.SEALED |
6525 Modifiers.OVERRIDE |
6526 Modifiers.ABSTRACT |
6527 Modifiers.UNSAFE |
6528 Modifiers.EXTERN |
6529 Modifiers.METHOD_YIELDS |
6530 Modifiers.VIRTUAL;
6532 const int AllowedInterfaceModifiers =
6533 Modifiers.NEW;
6535 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6536 MemberName name, Attributes attrs, Accessor get_block,
6537 Accessor set_block)
6538 : base (parent, type, mod,
6539 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6540 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs)
6542 if (get_block == null)
6543 Get = new GetMethod (this);
6544 else
6545 Get = new GetMethod (this, get_block);
6547 if (set_block == null)
6548 Set = new SetMethod (this);
6549 else
6550 Set = new SetMethod (this, set_block);
6553 public override bool Define ()
6555 if (!DoDefineBase ())
6556 return false;
6558 if (!base.Define ())
6559 return false;
6561 if (!CheckBase ())
6562 return false;
6564 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6566 if (!Get.IsDummy) {
6567 GetBuilder = Get.Define (Parent);
6568 if (GetBuilder == null)
6569 return false;
6572 SetBuilder = Set.Define (Parent);
6573 if (!Set.IsDummy) {
6574 if (SetBuilder == null)
6575 return false;
6578 // FIXME - PropertyAttributes.HasDefault ?
6580 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6581 MemberName.ToString (), PropertyAttributes.None, MemberType, null);
6583 if (!Get.IsDummy)
6584 PropertyBuilder.SetGetMethod (GetBuilder);
6586 if (!Set.IsDummy)
6587 PropertyBuilder.SetSetMethod (SetBuilder);
6589 TypeManager.RegisterProperty (PropertyBuilder, this);
6590 return true;
6594 /// </summary>
6595 /// Gigantic workaround for lameness in SRE follows :
6596 /// This class derives from EventInfo and attempts to basically
6597 /// wrap around the EventBuilder so that FindMembers can quickly
6598 /// return this in it search for members
6599 /// </summary>
6600 public class MyEventBuilder : EventInfo {
6603 // We use this to "point" to our Builder which is
6604 // not really a MemberInfo
6606 EventBuilder MyBuilder;
6609 // We "catch" and wrap these methods
6611 MethodInfo raise, remove, add;
6613 EventAttributes attributes;
6614 Type declaring_type, reflected_type, event_type;
6615 string name;
6617 Event my_event;
6619 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6621 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6623 // And now store the values in our own fields.
6625 declaring_type = type_builder;
6627 reflected_type = type_builder;
6629 attributes = event_attr;
6630 this.name = name;
6631 my_event = ev;
6632 this.event_type = event_type;
6636 // Methods that you have to override. Note that you only need
6637 // to "implement" the variants that take the argument (those are
6638 // the "abstract" methods, the others (GetAddMethod()) are
6639 // regular.
6641 public override MethodInfo GetAddMethod (bool nonPublic)
6643 return add;
6646 public override MethodInfo GetRemoveMethod (bool nonPublic)
6648 return remove;
6651 public override MethodInfo GetRaiseMethod (bool nonPublic)
6653 return raise;
6657 // These methods make "MyEventInfo" look like a Builder
6659 public void SetRaiseMethod (MethodBuilder raiseMethod)
6661 raise = raiseMethod;
6662 MyBuilder.SetRaiseMethod (raiseMethod);
6665 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6667 remove = removeMethod;
6668 MyBuilder.SetRemoveOnMethod (removeMethod);
6671 public void SetAddOnMethod (MethodBuilder addMethod)
6673 add = addMethod;
6674 MyBuilder.SetAddOnMethod (addMethod);
6677 public void SetCustomAttribute (CustomAttributeBuilder cb)
6679 MyBuilder.SetCustomAttribute (cb);
6682 public override object [] GetCustomAttributes (bool inherit)
6684 // FIXME : There's nothing which can be seemingly done here because
6685 // we have no way of getting at the custom attribute objects of the
6686 // EventBuilder !
6687 return null;
6690 public override object [] GetCustomAttributes (Type t, bool inherit)
6692 // FIXME : Same here !
6693 return null;
6696 public override bool IsDefined (Type t, bool b)
6698 return true;
6701 public override EventAttributes Attributes {
6702 get {
6703 return attributes;
6707 public override string Name {
6708 get {
6709 return name;
6713 public override Type DeclaringType {
6714 get {
6715 return declaring_type;
6719 public override Type ReflectedType {
6720 get {
6721 return reflected_type;
6725 public Type EventType {
6726 get {
6727 return event_type;
6731 public void SetUsed ()
6733 if (my_event != null) {
6734 my_event.SetAssigned ();
6735 my_event.SetMemberIsUsed ();
6740 /// <summary>
6741 /// For case when event is declared like property (with add and remove accessors).
6742 /// </summary>
6743 public class EventProperty: Event {
6745 static string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
6747 public EventProperty (DeclSpace parent, Expression type, int mod_flags,
6748 bool is_iface, MemberName name,
6749 Attributes attrs, Accessor add, Accessor remove)
6750 : base (parent, type, mod_flags, is_iface, name, attrs)
6752 Add = new AddDelegateMethod (this, add);
6753 Remove = new RemoveDelegateMethod (this, remove);
6755 // For this event syntax we don't report error CS0067
6756 // because it is hard to do it.
6757 SetAssigned ();
6760 public override string[] ValidAttributeTargets {
6761 get {
6762 return attribute_targets;
6767 /// <summary>
6768 /// Event is declared like field.
6769 /// </summary>
6770 public class EventField : Event {
6772 static string[] attribute_targets = new string [] { "event", "field", "method" };
6773 static string[] attribute_targets_interface = new string[] { "event", "method" };
6775 public EventField (DeclSpace parent, Expression type, int mod_flags,
6776 bool is_iface, MemberName name,
6777 Attributes attrs)
6778 : base (parent, type, mod_flags, is_iface, name, attrs)
6780 Add = new AddDelegateMethod (this);
6781 Remove = new RemoveDelegateMethod (this);
6784 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6786 if (a.Target == AttributeTargets.Field) {
6787 FieldBuilder.SetCustomAttribute (cb);
6788 return;
6791 if (a.Target == AttributeTargets.Method) {
6792 Add.ApplyAttributeBuilder (a, cb);
6793 Remove.ApplyAttributeBuilder (a, cb);
6794 return;
6797 base.ApplyAttributeBuilder (a, cb);
6800 public override bool Define()
6802 if (!base.Define ())
6803 return false;
6805 if (initializer != null) {
6806 if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
6807 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
6808 GetSignatureForError ());
6809 return false;
6813 return true;
6816 public override string[] ValidAttributeTargets {
6817 get {
6818 return IsInterface ? attribute_targets_interface : attribute_targets;
6823 public abstract class Event : FieldBase {
6825 protected sealed class AddDelegateMethod: DelegateMethod
6828 public AddDelegateMethod (Event method):
6829 base (method, "add_")
6833 public AddDelegateMethod (Event method, Accessor accessor):
6834 base (method, accessor, "add_")
6838 protected override MethodInfo DelegateMethodInfo {
6839 get {
6840 return TypeManager.delegate_combine_delegate_delegate;
6846 protected sealed class RemoveDelegateMethod: DelegateMethod
6848 public RemoveDelegateMethod (Event method):
6849 base (method, "remove_")
6853 public RemoveDelegateMethod (Event method, Accessor accessor):
6854 base (method, accessor, "remove_")
6858 protected override MethodInfo DelegateMethodInfo {
6859 get {
6860 return TypeManager.delegate_remove_delegate_delegate;
6866 public abstract class DelegateMethod : AbstractPropertyEventMethod
6868 protected readonly Event method;
6869 ImplicitParameter param_attr;
6871 static string[] attribute_targets = new string [] { "method", "param", "return" };
6873 public DelegateMethod (Event method, string prefix)
6874 : base (method, prefix)
6876 this.method = method;
6879 public DelegateMethod (Event method, Accessor accessor, string prefix)
6880 : base (method, accessor, prefix)
6882 this.method = method;
6885 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6887 if (a.Target == AttributeTargets.Parameter) {
6888 if (param_attr == null)
6889 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6891 param_attr.ApplyAttributeBuilder (a, cb);
6892 return;
6895 base.ApplyAttributeBuilder (a, cb);
6898 public override AttributeTargets AttributeTargets {
6899 get {
6900 return AttributeTargets.Method;
6904 public override bool IsClsComplianceRequired ()
6906 return method.IsClsComplianceRequired ();
6909 public MethodBuilder Define (DeclSpace parent)
6911 method_data = new MethodData (method, method.ModFlags,
6912 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6914 if (!method_data.Define (parent))
6915 return null;
6917 MethodBuilder mb = method_data.MethodBuilder;
6918 ParameterInfo.ApplyAttributes (mb);
6919 return mb;
6923 protected override void EmitMethod (DeclSpace parent)
6925 if (block != null) {
6926 base.EmitMethod (parent);
6927 return;
6930 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6931 return;
6933 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6934 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6936 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6937 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6938 ig.Emit (OpCodes.Ldsfld, field_info);
6939 ig.Emit (OpCodes.Ldarg_0);
6940 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6941 ig.Emit (OpCodes.Castclass, method.MemberType);
6942 ig.Emit (OpCodes.Stsfld, field_info);
6943 } else {
6944 ig.Emit (OpCodes.Ldarg_0);
6945 ig.Emit (OpCodes.Ldarg_0);
6946 ig.Emit (OpCodes.Ldfld, field_info);
6947 ig.Emit (OpCodes.Ldarg_1);
6948 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6949 ig.Emit (OpCodes.Castclass, method.MemberType);
6950 ig.Emit (OpCodes.Stfld, field_info);
6952 ig.Emit (OpCodes.Ret);
6955 protected abstract MethodInfo DelegateMethodInfo { get; }
6957 public override Type ReturnType {
6958 get {
6959 return TypeManager.void_type;
6963 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6965 return new EmitContext (
6966 ds, method.Parent, Location, ig, ReturnType,
6967 method.ModFlags, false);
6970 public override ObsoleteAttribute GetObsoleteAttribute ()
6972 return method.GetObsoleteAttribute ();
6975 public override string[] ValidAttributeTargets {
6976 get {
6977 return attribute_targets;
6981 public override Parameters ParameterInfo {
6982 get {
6983 return method.parameters;
6990 const int AllowedModifiers =
6991 Modifiers.NEW |
6992 Modifiers.PUBLIC |
6993 Modifiers.PROTECTED |
6994 Modifiers.INTERNAL |
6995 Modifiers.PRIVATE |
6996 Modifiers.STATIC |
6997 Modifiers.VIRTUAL |
6998 Modifiers.SEALED |
6999 Modifiers.OVERRIDE |
7000 Modifiers.UNSAFE |
7001 Modifiers.ABSTRACT;
7003 const int AllowedInterfaceModifiers =
7004 Modifiers.NEW;
7006 public DelegateMethod Add, Remove;
7007 public MyEventBuilder EventBuilder;
7008 public MethodBuilder AddBuilder, RemoveBuilder;
7009 Parameters parameters;
7011 protected Event (DeclSpace parent, Expression type, int mod_flags,
7012 bool is_iface, MemberName name, Attributes attrs)
7013 : base (parent, type, mod_flags,
7014 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7015 name, attrs)
7017 IsInterface = is_iface;
7020 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7022 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
7023 a.Error_InvalidSecurityParent ();
7024 return;
7027 EventBuilder.SetCustomAttribute (cb);
7030 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7032 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7035 public override AttributeTargets AttributeTargets {
7036 get {
7037 return AttributeTargets.Event;
7041 public override bool Define ()
7043 EventAttributes e_attr;
7044 e_attr = EventAttributes.None;
7046 if (!DoDefineBase ())
7047 return false;
7049 if (!DoDefine ())
7050 return false;
7052 if (!TypeManager.IsDelegateType (MemberType)) {
7053 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7054 return false;
7057 parameters = new Parameters (
7058 new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
7059 new Type[] { MemberType } );
7061 if (!CheckBase ())
7062 return false;
7065 // Now define the accessors
7068 AddBuilder = Add.Define (Parent);
7069 if (AddBuilder == null)
7070 return false;
7072 RemoveBuilder = Remove.Define (Parent);
7073 if (RemoveBuilder == null)
7074 return false;
7076 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
7078 if (Add.Block == null && Remove.Block == null && !IsInterface) {
7079 FieldBuilder = Parent.TypeBuilder.DefineField (
7080 Name, MemberType,
7081 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7082 TypeManager.RegisterPrivateFieldOfEvent (
7083 (EventInfo) EventBuilder, FieldBuilder);
7084 TypeManager.RegisterFieldBase (FieldBuilder, this);
7087 EventBuilder.SetAddOnMethod (AddBuilder);
7088 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7090 TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
7091 return true;
7094 protected override bool CheckBase ()
7096 if (!base.CheckBase ())
7097 return false;
7099 if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
7100 if (!(conflict_symbol is EventInfo)) {
7101 Report.SymbolRelatedToPreviousError (conflict_symbol);
7102 Report.Error (72, Location, "Event `{0}' can override only event", GetSignatureForError ());
7103 return false;
7107 return true;
7110 public override void Emit ()
7112 if (OptAttributes != null) {
7113 OptAttributes.Emit ();
7116 Add.Emit (Parent);
7117 Remove.Emit (Parent);
7119 base.Emit ();
7122 public override string GetSignatureForError ()
7124 return base.GetSignatureForError ();
7128 // Represents header string for documentation comment.
7130 public override string DocCommentHeader {
7131 get { return "E:"; }
7136 public class Indexer : PropertyBase, IIteratorContainer {
7138 class GetIndexerMethod : GetMethod
7140 public GetIndexerMethod (MethodCore method):
7141 base (method)
7145 public GetIndexerMethod (MethodCore method, Accessor accessor):
7146 base (method, accessor)
7150 public override Parameters ParameterInfo {
7151 get {
7152 return method.ParameterInfo;
7157 class SetIndexerMethod: SetMethod
7159 public SetIndexerMethod (MethodCore method):
7160 base (method)
7164 public SetIndexerMethod (MethodCore method, Accessor accessor):
7165 base (method, accessor)
7169 protected override void DefineParameters ()
7171 parameters = Parameters.MergeGenerated (method.Parameters,
7172 new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
7176 const int AllowedModifiers =
7177 Modifiers.NEW |
7178 Modifiers.PUBLIC |
7179 Modifiers.PROTECTED |
7180 Modifiers.INTERNAL |
7181 Modifiers.PRIVATE |
7182 Modifiers.VIRTUAL |
7183 Modifiers.SEALED |
7184 Modifiers.OVERRIDE |
7185 Modifiers.UNSAFE |
7186 Modifiers.EXTERN |
7187 Modifiers.ABSTRACT;
7189 const int AllowedInterfaceModifiers =
7190 Modifiers.NEW;
7193 // Are we implementing an interface ?
7195 public Indexer (DeclSpace parent, Expression type, MemberName name, int mod,
7196 bool is_iface, Parameters parameters, Attributes attrs,
7197 Accessor get_block, Accessor set_block)
7198 : base (parent, type, mod,
7199 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7200 is_iface, name, parameters, attrs)
7202 if (get_block == null)
7203 Get = new GetIndexerMethod (this);
7204 else
7205 Get = new GetIndexerMethod (this, get_block);
7207 if (set_block == null)
7208 Set = new SetIndexerMethod (this);
7209 else
7210 Set = new SetIndexerMethod (this, set_block);
7213 public override bool Define ()
7215 if (!DoDefineBase ())
7216 return false;
7218 if (!base.Define ())
7219 return false;
7221 if (MemberType == TypeManager.void_type) {
7222 Report.Error (620, Location, "Indexers cannot have void type");
7223 return false;
7226 if (OptAttributes != null) {
7227 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
7228 if (indexer_attr != null) {
7229 // Remove the attribute from the list because it is not emitted
7230 OptAttributes.Attrs.Remove (indexer_attr);
7232 string name = indexer_attr.GetIndexerAttributeValue ();
7233 if (name == null)
7234 return false;
7236 ShortName = name;
7238 if (IsExplicitImpl) {
7239 Report.Error (415, indexer_attr.Location,
7240 "The `IndexerName' attribute is valid only on an " +
7241 "indexer that is not an explicit interface member declaration");
7242 return false;
7245 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7246 Report.Error (609, indexer_attr.Location,
7247 "Cannot set the `IndexerName' attribute on an indexer marked override");
7248 return false;
7253 if (InterfaceType != null) {
7254 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7255 if (base_IndexerName != Name)
7256 ShortName = base_IndexerName;
7259 if (!ParentContainer.AddToMemberContainer (this) ||
7260 !ParentContainer.AddToMemberContainer (Get) || !ParentContainer.AddToMemberContainer (Set))
7261 return false;
7263 if (!CheckBase ())
7264 return false;
7266 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7267 if (!Get.IsDummy){
7268 GetBuilder = Get.Define (Parent);
7269 if (GetBuilder == null)
7270 return false;
7273 // Setup iterator if we are one
7275 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
7276 Iterator iterator = new Iterator (
7277 Get, Parent, null, ModFlags);
7279 if (!iterator.DefineIterator ())
7280 return false;
7284 SetBuilder = Set.Define (Parent);
7285 if (!Set.IsDummy){
7286 if (SetBuilder == null)
7287 return false;
7291 // Now name the parameters
7293 Parameter [] p = Parameters.FixedParameters;
7294 if (p != null) {
7295 // TODO: should be done in parser and it needs to do cycle
7296 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7297 Report.Error (631, Location, "ref and out are not valid in this context");
7298 return false;
7302 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7303 Name, PropertyAttributes.None, MemberType, ParameterTypes);
7305 if (!Get.IsDummy)
7306 PropertyBuilder.SetGetMethod (GetBuilder);
7308 if (!Set.IsDummy)
7309 PropertyBuilder.SetSetMethod (SetBuilder);
7311 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
7313 return true;
7316 public override string GetSignatureForError ()
7318 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7319 if (MemberName.Left != null) {
7320 sb.Append ('.');
7321 sb.Append (MemberName.Left);
7324 sb.Append (".this");
7325 sb.Append (Parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7326 return sb.ToString ();
7329 public override bool MarkForDuplicationCheck ()
7331 caching_flags |= Flags.TestMethodDuplication;
7332 return true;
7336 public class Operator : MethodOrOperator, IIteratorContainer {
7338 const int AllowedModifiers =
7339 Modifiers.PUBLIC |
7340 Modifiers.UNSAFE |
7341 Modifiers.EXTERN |
7342 Modifiers.STATIC;
7344 public enum OpType : byte {
7346 // Unary operators
7347 LogicalNot,
7348 OnesComplement,
7349 Increment,
7350 Decrement,
7351 True,
7352 False,
7354 // Unary and Binary operators
7355 Addition,
7356 Subtraction,
7358 UnaryPlus,
7359 UnaryNegation,
7361 // Binary operators
7362 Multiply,
7363 Division,
7364 Modulus,
7365 BitwiseAnd,
7366 BitwiseOr,
7367 ExclusiveOr,
7368 LeftShift,
7369 RightShift,
7370 Equality,
7371 Inequality,
7372 GreaterThan,
7373 LessThan,
7374 GreaterThanOrEqual,
7375 LessThanOrEqual,
7377 // Implicit and Explicit
7378 Implicit,
7379 Explicit,
7381 // Just because of enum
7385 public readonly OpType OperatorType;
7387 public Operator (DeclSpace parent, OpType type, Expression ret_type,
7388 int mod_flags, Parameters parameters,
7389 ToplevelBlock block, Attributes attrs, Location loc)
7390 : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
7391 new MemberName ("op_" + type, loc), attrs, parameters)
7393 OperatorType = type;
7394 Block = block;
7397 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7399 if (a.Type == TypeManager.conditional_attribute_type) {
7400 Error_ConditionalAttributeIsNotValid ();
7401 return;
7404 base.ApplyAttributeBuilder (a, cb);
7407 protected override bool CheckForDuplications ()
7409 ArrayList ar = ParentContainer.Operators;
7410 if (ar != null) {
7411 int arLen = ar.Count;
7413 for (int i = 0; i < arLen; i++) {
7414 Operator o = (Operator) ar [i];
7415 if (IsDuplicateImplementation (o))
7416 return false;
7420 ar = ParentContainer.Methods;
7421 if (ar != null) {
7422 int arLen = ar.Count;
7424 for (int i = 0; i < arLen; i++) {
7425 Method m = (Method) ar [i];
7426 if (IsDuplicateImplementation (m))
7427 return false;
7431 return true;
7434 public override bool Define ()
7436 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7437 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7438 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7439 return false;
7442 if (!base.Define ())
7443 return false;
7445 if (MemberType == TypeManager.void_type) {
7446 Report.Error (590, Location, "User-defined operators cannot return void");
7447 return false;
7450 Type declaring_type = MethodData.DeclaringType;
7451 Type return_type = MemberType;
7452 Type first_arg_type = ParameterTypes [0];
7454 // Rules for conversion operators
7456 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7457 if (first_arg_type == return_type && first_arg_type == declaring_type){
7458 Report.Error (555, Location,
7459 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7460 return false;
7463 if (first_arg_type != declaring_type && return_type != declaring_type){
7464 Report.Error (
7465 556, Location,
7466 "User-defined conversion must convert to or from the " +
7467 "enclosing type");
7468 return false;
7471 if (first_arg_type.IsInterface || return_type.IsInterface){
7472 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7473 GetSignatureForError ());
7474 return false;
7477 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
7478 if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
7479 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
7480 GetSignatureForError ());
7481 return false;
7483 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
7484 GetSignatureForError ());
7485 return false;
7487 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7488 if (first_arg_type != declaring_type || ParameterTypes [1] != TypeManager.int32_type) {
7489 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");
7490 return false;
7492 } else if (Parameters.Count == 1) {
7493 // Checks for Unary operators
7495 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7496 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
7497 Report.Error (448, Location,
7498 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7499 return false;
7501 if (first_arg_type != declaring_type) {
7502 Report.Error (
7503 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7504 return false;
7508 if (first_arg_type != declaring_type){
7509 Report.Error (
7510 562, Location,
7511 "The parameter of a unary operator must be the " +
7512 "containing type");
7513 return false;
7516 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7517 if (return_type != TypeManager.bool_type){
7518 Report.Error (
7519 215, Location,
7520 "The return type of operator True or False " +
7521 "must be bool");
7522 return false;
7526 } else {
7527 // Checks for Binary operators
7529 if (first_arg_type != declaring_type &&
7530 ParameterTypes [1] != declaring_type){
7531 Report.Error (
7532 563, Location,
7533 "One of the parameters of a binary operator must " +
7534 "be the containing type");
7535 return false;
7539 return true;
7542 protected override bool DoDefine ()
7544 if (!base.DoDefine ())
7545 return false;
7547 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7548 return true;
7551 public override void Emit ()
7553 base.Emit ();
7555 Parameters.ApplyAttributes (MethodBuilder);
7558 // abstract or extern methods have no bodies
7560 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7561 return;
7563 EmitContext ec;
7564 if ((flags & MethodAttributes.PinvokeImpl) == 0)
7565 ec = CreateEmitContext (Parent, MethodBuilder.GetILGenerator ());
7566 else
7567 ec = CreateEmitContext (Parent, null);
7569 SourceMethod source = SourceMethod.Create (Parent, MethodBuilder, Block);
7570 ec.EmitTopBlock (this, Block);
7572 if (source != null)
7573 source.CloseMethod ();
7575 Block = null;
7578 // Operator cannot be override
7579 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7581 return null;
7584 public static string GetName (OpType ot)
7586 switch (ot){
7587 case OpType.LogicalNot:
7588 return "!";
7589 case OpType.OnesComplement:
7590 return "~";
7591 case OpType.Increment:
7592 return "++";
7593 case OpType.Decrement:
7594 return "--";
7595 case OpType.True:
7596 return "true";
7597 case OpType.False:
7598 return "false";
7599 case OpType.Addition:
7600 return "+";
7601 case OpType.Subtraction:
7602 return "-";
7603 case OpType.UnaryPlus:
7604 return "+";
7605 case OpType.UnaryNegation:
7606 return "-";
7607 case OpType.Multiply:
7608 return "*";
7609 case OpType.Division:
7610 return "/";
7611 case OpType.Modulus:
7612 return "%";
7613 case OpType.BitwiseAnd:
7614 return "&";
7615 case OpType.BitwiseOr:
7616 return "|";
7617 case OpType.ExclusiveOr:
7618 return "^";
7619 case OpType.LeftShift:
7620 return "<<";
7621 case OpType.RightShift:
7622 return ">>";
7623 case OpType.Equality:
7624 return "==";
7625 case OpType.Inequality:
7626 return "!=";
7627 case OpType.GreaterThan:
7628 return ">";
7629 case OpType.LessThan:
7630 return "<";
7631 case OpType.GreaterThanOrEqual:
7632 return ">=";
7633 case OpType.LessThanOrEqual:
7634 return "<=";
7635 case OpType.Implicit:
7636 return "implicit";
7637 case OpType.Explicit:
7638 return "explicit";
7639 default: return "";
7643 public static OpType GetOperatorType (string name)
7645 if (name.StartsWith ("op_")){
7646 for (int i = 0; i < Unary.oper_names.Length; ++i) {
7647 if (Unary.oper_names [i] == name)
7648 return (OpType)i;
7651 for (int i = 0; i < Binary.oper_names.Length; ++i) {
7652 if (Binary.oper_names [i] == name)
7653 return (OpType)i;
7656 return OpType.TOP;
7659 public override string GetSignatureForError ()
7661 StringBuilder sb = new StringBuilder ();
7662 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7663 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
7665 else {
7666 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
7669 sb.Append (Parameters.GetSignatureForError ());
7670 return sb.ToString ();
7675 // This is used to compare method signatures
7677 struct MethodSignature {
7678 public string Name;
7679 public Type RetType;
7680 public Type [] Parameters;
7682 /// <summary>
7683 /// This delegate is used to extract methods which have the
7684 /// same signature as the argument
7685 /// </summary>
7686 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7688 public MethodSignature (string name, Type ret_type, Type [] parameters)
7690 Name = name;
7691 RetType = ret_type;
7693 if (parameters == null)
7694 Parameters = Type.EmptyTypes;
7695 else
7696 Parameters = parameters;
7699 public override string ToString ()
7701 string pars = "";
7702 if (Parameters.Length != 0){
7703 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7704 for (int i = 0; i < Parameters.Length; i++){
7705 sb.Append (Parameters [i]);
7706 if (i+1 < Parameters.Length)
7707 sb.Append (", ");
7709 pars = sb.ToString ();
7712 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7715 public override int GetHashCode ()
7717 return Name.GetHashCode ();
7720 public override bool Equals (Object o)
7722 MethodSignature other = (MethodSignature) o;
7724 if (other.Name != Name)
7725 return false;
7727 if (other.RetType != RetType)
7728 return false;
7730 if (Parameters == null){
7731 if (other.Parameters == null)
7732 return true;
7733 return false;
7736 if (other.Parameters == null)
7737 return false;
7739 int c = Parameters.Length;
7740 if (other.Parameters.Length != c)
7741 return false;
7743 for (int i = 0; i < c; i++)
7744 if (other.Parameters [i] != Parameters [i])
7745 return false;
7747 return true;
7750 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7752 MethodSignature sig = (MethodSignature) filter_criteria;
7754 if (m.Name != sig.Name)
7755 return false;
7757 Type ReturnType;
7758 MethodInfo mi = m as MethodInfo;
7759 PropertyInfo pi = m as PropertyInfo;
7761 if (mi != null)
7762 ReturnType = mi.ReturnType;
7763 else if (pi != null)
7764 ReturnType = pi.PropertyType;
7765 else
7766 return false;
7769 // we use sig.RetType == null to mean `do not check the
7770 // method return value.
7772 if (sig.RetType != null)
7773 if (ReturnType != sig.RetType)
7774 return false;
7776 Type [] args;
7777 if (mi != null)
7778 args = TypeManager.GetParameterData (mi).Types;
7779 else
7780 args = TypeManager.GetArgumentTypes (pi);
7781 Type [] sigp = sig.Parameters;
7783 if (args.Length != sigp.Length)
7784 return false;
7786 for (int i = args.Length; i > 0; ){
7787 i--;
7788 if (args [i] != sigp [i])
7789 return false;
7791 return true;