Revert 74623/74624 to fix build.
[mcs.git] / mcs / class.cs
blob8f3425cde6451837180a2156b53a1cadab2ac2a1
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;
45 #if BOOTSTRAP_WITH_OLDLIB
46 using XmlElement = System.Object;
47 #else
48 using System.Xml;
49 #endif
51 using Mono.CompilerServices.SymbolWriter;
53 namespace Mono.CSharp {
55 public enum Kind {
56 Root,
57 Struct,
58 Class,
59 Interface,
60 Enum
63 /// <summary>
64 /// This is the base class for structs and classes.
65 /// </summary>
66 public abstract class TypeContainer : DeclSpace, IMemberContainer {
68 public class MemberCoreArrayList: ArrayList
70 /// <summary>
71 /// Defines the MemberCore objects that are in this array
72 /// </summary>
73 public virtual void DefineContainerMembers ()
75 foreach (MemberCore mc in this) {
76 try {
77 mc.Define ();
78 } catch (Exception e) {
79 throw new InternalErrorException (mc, e);
84 public virtual void Emit ()
86 foreach (MemberCore mc in this)
87 mc.Emit ();
91 public class MethodArrayList : MemberCoreArrayList
93 [Flags]
94 enum CachedMethods {
95 Equals = 1,
96 GetHashCode = 1 << 1
99 CachedMethods cached_method;
100 TypeContainer container;
102 public MethodArrayList (TypeContainer container)
104 this.container = container;
107 /// <summary>
108 /// Method container contains Equals method
109 /// </summary>
110 public bool HasEquals {
111 set {
112 cached_method |= CachedMethods.Equals;
115 get {
116 return (cached_method & CachedMethods.Equals) != 0;
120 /// <summary>
121 /// Method container contains GetHashCode method
122 /// </summary>
123 public bool HasGetHashCode {
124 set {
125 cached_method |= CachedMethods.GetHashCode;
128 get {
129 return (cached_method & CachedMethods.GetHashCode) != 0;
133 public override void DefineContainerMembers ()
135 base.DefineContainerMembers ();
137 if (HasEquals && !HasGetHashCode) {
138 Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
143 public sealed class IndexerArrayList : MemberCoreArrayList
145 /// <summary>
146 /// The indexer name for this container
147 /// </summary>
148 public string IndexerName = DefaultIndexerName;
150 bool seen_normal_indexers = false;
152 TypeContainer container;
154 public IndexerArrayList (TypeContainer container)
156 this.container = container;
159 /// <summary>
160 /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
161 /// class is consistent. Either it is `Item' or it is the name defined by all the
162 /// indexers with the `IndexerName' attribute.
164 /// Turns out that the IndexerNameAttribute is applied to each indexer,
165 /// but it is never emitted, instead a DefaultMember attribute is attached
166 /// to the class.
167 /// </summary>
168 public override void DefineContainerMembers()
170 base.DefineContainerMembers ();
172 string class_indexer_name = null;
175 // If there's both an explicit and an implicit interface implementation, the
176 // explicit one actually implements the interface while the other one is just
177 // a normal indexer. See bug #37714.
180 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
181 foreach (Indexer i in this) {
182 if (i.InterfaceType != null) {
183 if (seen_normal_indexers)
184 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
185 continue;
188 seen_normal_indexers = true;
190 if (class_indexer_name == null) {
191 class_indexer_name = i.ShortName;
192 continue;
195 if (i.ShortName != class_indexer_name)
196 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");
199 if (class_indexer_name != null)
200 IndexerName = class_indexer_name;
203 public override void Emit ()
205 base.Emit ();
207 if (!seen_normal_indexers)
208 return;
210 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
211 container.TypeBuilder.SetCustomAttribute (cb);
215 public class OperatorArrayList: MemberCoreArrayList
217 TypeContainer container;
219 public OperatorArrayList (TypeContainer container)
221 this.container = container;
225 // Operator pair checking
227 class OperatorEntry
229 public int flags;
230 public Type ret_type;
231 public Type type1, type2;
232 public Operator op;
233 public Operator.OpType ot;
235 public OperatorEntry (int f, Operator o)
237 flags = f;
239 ret_type = o.MemberType;
240 Type [] pt = o.ParameterTypes;
241 type1 = pt [0];
242 type2 = pt [1];
243 op = o;
244 ot = o.OperatorType;
247 public override int GetHashCode ()
249 return ret_type.GetHashCode ();
252 public override bool Equals (object o)
254 OperatorEntry other = (OperatorEntry) o;
256 if (other.ret_type != ret_type)
257 return false;
258 if (other.type1 != type1)
259 return false;
260 if (other.type2 != type2)
261 return false;
262 return true;
267 // Checks that some operators come in pairs:
268 // == and !=
269 // > and <
270 // >= and <=
271 // true and false
273 // They are matched based on the return type and the argument types
275 void CheckPairedOperators ()
277 IDictionary pairs = new HybridDictionary ();
278 Operator true_op = null;
279 Operator false_op = null;
280 bool has_equality_or_inequality = false;
282 // Register all the operators we care about.
283 foreach (Operator op in this){
284 int reg = 0;
286 // Skip erroneous code.
287 if (op.MethodBuilder == null)
288 continue;
290 switch (op.OperatorType){
291 case Operator.OpType.Equality:
292 reg = 1;
293 has_equality_or_inequality = true;
294 break;
295 case Operator.OpType.Inequality:
296 reg = 2;
297 has_equality_or_inequality = true;
298 break;
300 case Operator.OpType.True:
301 true_op = op;
302 break;
303 case Operator.OpType.False:
304 false_op = op;
305 break;
307 case Operator.OpType.GreaterThan:
308 reg = 1; break;
309 case Operator.OpType.LessThan:
310 reg = 2; break;
312 case Operator.OpType.GreaterThanOrEqual:
313 reg = 1; break;
314 case Operator.OpType.LessThanOrEqual:
315 reg = 2; break;
317 if (reg == 0)
318 continue;
320 OperatorEntry oe = new OperatorEntry (reg, op);
322 object o = pairs [oe];
323 if (o == null)
324 pairs [oe] = oe;
325 else {
326 oe = (OperatorEntry) o;
327 oe.flags |= reg;
331 if (true_op != null){
332 if (false_op == null)
333 Report.Error (216, true_op.Location, "The operator `{0}' requires a matching operator `false' to also be defined",
334 true_op.GetSignatureForError ());
335 } else if (false_op != null)
336 Report.Error (216, false_op.Location, "The operator `{0}' requires a matching operator `true' to also be defined",
337 false_op.GetSignatureForError ());
340 // Look for the mistakes.
342 foreach (DictionaryEntry de in pairs){
343 OperatorEntry oe = (OperatorEntry) de.Key;
345 if (oe.flags == 3)
346 continue;
348 string s = "";
349 switch (oe.ot){
350 case Operator.OpType.Equality:
351 s = "!=";
352 break;
353 case Operator.OpType.Inequality:
354 s = "==";
355 break;
356 case Operator.OpType.GreaterThan:
357 s = "<";
358 break;
359 case Operator.OpType.LessThan:
360 s = ">";
361 break;
362 case Operator.OpType.GreaterThanOrEqual:
363 s = "<=";
364 break;
365 case Operator.OpType.LessThanOrEqual:
366 s = ">=";
367 break;
369 Report.Error (216, oe.op.Location,
370 "The operator `{0}' requires a matching operator `{1}' to also be defined",
371 oe.op.GetSignatureForError (), s);
374 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
375 if (container.Methods == null || !container.Methods.HasEquals)
376 Report.Warning (660, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
378 if (container.Methods == null || !container.Methods.HasGetHashCode)
379 Report.Warning (661, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
383 public override void DefineContainerMembers ()
385 base.DefineContainerMembers ();
386 CheckPairedOperators ();
391 // Whether this is a struct, class or interface
392 public readonly Kind Kind;
394 // Holds a list of classes and structures
395 protected ArrayList types;
397 // Holds the list of properties
398 MemberCoreArrayList properties;
400 // Holds the list of enumerations
401 MemberCoreArrayList enums;
403 // Holds the list of delegates
404 MemberCoreArrayList delegates;
406 // Holds the list of constructors
407 protected MemberCoreArrayList instance_constructors;
409 // Holds the list of fields
410 MemberCoreArrayList fields;
412 // Holds a list of fields that have initializers
413 protected ArrayList initialized_fields;
415 // Holds a list of static fields that have initializers
416 protected ArrayList initialized_static_fields;
418 // Holds the list of constants
419 MemberCoreArrayList constants;
421 // Holds the list of
422 MemberCoreArrayList interfaces;
424 // Holds the methods.
425 MethodArrayList methods;
427 // Holds the events
428 protected MemberCoreArrayList events;
430 // Holds the indexers
431 IndexerArrayList indexers;
433 // Holds the operators
434 MemberCoreArrayList operators;
436 // Holds the compiler generated classes
437 ArrayList compiler_generated;
440 // Pointers to the default constructor and the default static constructor
442 protected Constructor default_constructor;
443 protected Constructor default_static_constructor;
446 // Points to the first non-static field added to the container.
448 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
449 // and the first one's as good as any.
451 FieldBase first_nonstatic_field = null;
454 // This one is computed after we can distinguish interfaces
455 // from classes from the arraylist `type_bases'
457 TypeExpr base_type;
458 TypeExpr[] iface_exprs;
459 Type GenericType;
461 ArrayList type_bases;
463 bool members_resolved;
464 bool members_resolved_ok;
465 bool members_defined;
466 bool members_defined_ok;
468 // The interfaces we implement.
469 protected Type[] ifaces;
471 // The base member cache and our member cache
472 MemberCache base_cache;
473 MemberCache member_cache;
475 public const string DefaultIndexerName = "Item";
477 #if GMCS_SOURCE
478 GenericTypeParameterBuilder[] gen_params;
479 #endif
481 ArrayList partial_parts;
483 /// <remarks>
484 /// The pending methods that need to be implemented
485 // (interfaces or abstract methods)
486 /// </remarks>
487 PendingImplementation pending;
489 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
490 Attributes attrs, Kind kind)
491 : base (ns, parent, name, attrs)
493 if (parent != null && parent.NamespaceEntry != ns)
494 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
496 this.Kind = kind;
497 this.PartialContainer = this;
500 public bool AddMember (MemberCore symbol)
502 return AddToContainer (symbol, symbol.MemberName.MethodName);
505 protected virtual bool AddMemberType (DeclSpace ds)
507 return AddToContainer (ds, ds.Basename);
510 public void AddConstant (Const constant)
512 if (!AddMember (constant))
513 return;
515 if (constants == null)
516 constants = new MemberCoreArrayList ();
518 constants.Add (constant);
521 public void AddEnum (Mono.CSharp.Enum e)
523 if (!AddMemberType (e))
524 return;
526 if (enums == null)
527 enums = new MemberCoreArrayList ();
529 enums.Add (e);
532 public TypeContainer AddTypeContainer (TypeContainer tc, bool is_interface)
534 if (!AddMemberType (tc))
535 return tc;
537 if (is_interface) {
538 if (interfaces == null)
539 interfaces = new MemberCoreArrayList ();
540 interfaces.Add (tc);
541 } else {
542 if (types == null)
543 types = new ArrayList (2);
544 types.Add (tc);
546 return tc;
549 public virtual TypeContainer AddPartial (TypeContainer nextPart, bool is_interface)
551 return AddPartial (nextPart, nextPart.Basename, is_interface);
554 protected TypeContainer AddPartial (TypeContainer nextPart, string name, bool is_interface)
556 nextPart.ModFlags |= Modifiers.PARTIAL;
557 TypeContainer tc = defined_names [name] as TypeContainer;
559 if (tc == null)
560 return AddTypeContainer (nextPart, is_interface);
562 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
563 Report.SymbolRelatedToPreviousError (tc);
564 Error_MissingPartialModifier (nextPart);
565 return tc;
568 if (tc.Kind != nextPart.Kind) {
569 Report.SymbolRelatedToPreviousError (tc);
570 Report.Error (261, nextPart.Location,
571 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
572 nextPart.GetSignatureForError ());
573 return tc;
576 if ((tc.ModFlags & Modifiers.Accessibility) != (nextPart.ModFlags & Modifiers.Accessibility) &&
577 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
578 (nextPart.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
579 Report.SymbolRelatedToPreviousError (tc);
580 Report.Error (262, nextPart.Location,
581 "Partial declarations of `{0}' have conflicting accessibility modifiers",
582 nextPart.GetSignatureForError ());
583 return tc;
586 if (tc.MemberName.IsGeneric) {
587 TypeParameter[] tc_names = tc.TypeParameters;
588 TypeParameterName[] part_names = nextPart.MemberName.TypeArguments.GetDeclarations ();
590 for (int i = 0; i < tc_names.Length; ++i) {
591 if (tc_names[i].Name == part_names[i].Name)
592 continue;
594 Report.SymbolRelatedToPreviousError (part_names[i].Location, "");
595 Report.Error (264, tc.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
596 tc.GetSignatureForError ());
597 return tc;
601 if (tc.partial_parts == null)
602 tc.partial_parts = new ArrayList (1);
604 tc.ModFlags |= nextPart.ModFlags;
605 if (nextPart.attributes != null) {
606 if (tc.attributes == null)
607 tc.attributes = nextPart.attributes;
608 else
609 tc.attributes.AddAttributes (nextPart.attributes.Attrs);
612 nextPart.PartialContainer = tc;
613 tc.partial_parts.Add (nextPart);
614 return tc;
617 public void AddDelegate (Delegate d)
619 if (!AddMemberType (d))
620 return;
622 if (delegates == null)
623 delegates = new MemberCoreArrayList ();
625 delegates.Add (d);
628 public void AddMethod (Method method)
630 if (!AddMember (method))
631 return;
633 if (methods == null)
634 methods = new MethodArrayList (this);
636 if (method.MemberName.Left != null)
637 methods.Insert (0, method);
638 else
639 methods.Add (method);
643 // Do not use this method: use AddMethod.
645 // This is only used by iterators.
647 public void AppendMethod (Method method)
649 if (!AddMember (method))
650 return;
652 if (methods == null)
653 methods = new MethodArrayList (this);
655 methods.Add (method);
658 public void AddConstructor (Constructor c)
660 if (c.Name != MemberName.Name) {
661 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
664 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
666 if (is_static){
667 if (default_static_constructor != null) {
668 Report.SymbolRelatedToPreviousError (default_static_constructor);
669 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
670 return;
673 default_static_constructor = c;
674 } else {
675 if (c.Parameters.Empty){
676 if (default_constructor != null) {
677 Report.SymbolRelatedToPreviousError (default_constructor);
678 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
679 return;
681 default_constructor = c;
684 if (instance_constructors == null)
685 instance_constructors = new MemberCoreArrayList ();
687 instance_constructors.Add (c);
691 internal static string Error111 {
692 get {
693 return "`{0}' is already defined. Rename this member or use different parameter types";
697 public void AddField (FieldBase field)
699 if (!AddMember (field))
700 return;
702 if (fields == null)
703 fields = new MemberCoreArrayList ();
705 fields.Add (field);
707 if ((field.ModFlags & Modifiers.STATIC) != 0)
708 return;
710 if (first_nonstatic_field == null) {
711 first_nonstatic_field = field;
712 return;
715 if (Kind == Kind.Struct &&
716 first_nonstatic_field.Parent != field.Parent &&
717 RootContext.WarningLevel >= 3) {
718 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
719 Report.Warning (282, 3, field.Location,
720 "struct instance field `{0}' found in different declaration from instance field `{1}'",
721 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
725 public void AddProperty (Property prop)
727 if (!AddMember (prop) ||
728 !AddMember (prop.Get) || !AddMember (prop.Set))
729 return;
731 if (properties == null)
732 properties = new MemberCoreArrayList ();
734 if (prop.MemberName.Left != null)
735 properties.Insert (0, prop);
736 else
737 properties.Add (prop);
740 public void AddEvent (Event e)
742 if (!AddMember (e))
743 return;
745 if (e is EventProperty) {
746 if (!AddMember (e.Add))
747 return;
749 if (!AddMember (e.Remove))
750 return;
753 if (events == null)
754 events = new MemberCoreArrayList ();
756 events.Add (e);
759 /// <summary>
760 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
761 /// </summary>
762 public void AddIndexer (Indexer i)
764 if (indexers == null)
765 indexers = new IndexerArrayList (this);
767 if (i.IsExplicitImpl)
768 indexers.Insert (0, i);
769 else
770 indexers.Add (i);
773 public void AddOperator (Operator op)
775 if (!AddMember (op))
776 return;
778 if (operators == null)
779 operators = new OperatorArrayList (this);
781 operators.Add (op);
784 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
786 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
788 if (compiler_generated == null)
789 compiler_generated = new ArrayList ();
791 compiler_generated.Add (c);
794 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
796 if (a.Type == TypeManager.default_member_type) {
797 if (Indexers != null) {
798 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
799 return;
803 base.ApplyAttributeBuilder (a, cb);
806 public override AttributeTargets AttributeTargets {
807 get {
808 throw new NotSupportedException ();
812 public ArrayList Types {
813 get {
814 return types;
818 public MethodArrayList Methods {
819 get {
820 return methods;
824 public ArrayList Constants {
825 get {
826 return constants;
830 public ArrayList Interfaces {
831 get {
832 return interfaces;
836 public ArrayList CompilerGenerated {
837 get {
838 return compiler_generated;
842 protected Type BaseType {
843 get {
844 return TypeBuilder.BaseType;
848 public ArrayList Bases {
849 get {
850 return type_bases;
853 set {
854 type_bases = value;
858 public ArrayList Fields {
859 get {
860 return fields;
864 public ArrayList InstanceConstructors {
865 get {
866 return instance_constructors;
870 public ArrayList Properties {
871 get {
872 return properties;
876 public ArrayList Events {
877 get {
878 return events;
882 public ArrayList Enums {
883 get {
884 return enums;
888 public ArrayList Indexers {
889 get {
890 return indexers;
894 public ArrayList Operators {
895 get {
896 return operators;
900 public ArrayList Delegates {
901 get {
902 return delegates;
906 protected override TypeAttributes TypeAttr {
907 get {
908 return Modifiers.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
912 public string IndexerName {
913 get {
914 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
918 public bool IsComImport {
919 get {
920 if (OptAttributes == null)
921 return false;
923 return OptAttributes.Contains (TypeManager.comimport_attr_type);
927 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
929 if ((field.ModFlags & Modifiers.STATIC) != 0){
930 if (initialized_static_fields == null)
931 initialized_static_fields = new ArrayList (4);
933 initialized_static_fields.Add (expression);
934 } else {
935 if (initialized_fields == null)
936 initialized_fields = new ArrayList (4);
938 initialized_fields.Add (expression);
943 // Emits the instance field initializers
945 public bool EmitFieldInitializers (EmitContext ec)
947 ArrayList fields;
949 if (ec.IsStatic){
950 fields = initialized_static_fields;
951 } else {
952 fields = initialized_fields;
955 if (fields == null)
956 return true;
958 foreach (FieldInitializer f in fields) {
959 f.EmitStatement (ec);
961 return true;
964 public override string DocComment {
965 get {
966 return comment;
968 set {
969 if (value == null)
970 return;
972 comment += value;
976 public PendingImplementation PendingImplementations {
977 get { return pending; }
980 public override bool GetClsCompliantAttributeValue ()
982 if (PartialContainer != this)
983 return PartialContainer.GetClsCompliantAttributeValue ();
985 return base.GetClsCompliantAttributeValue ();
988 public void AddBasesForPart (DeclSpace part, ArrayList bases)
990 // FIXME: get rid of partial_parts and store lists of bases of each part here
991 // assumed, not verified: 'part' is in 'partial_parts'
992 ((TypeContainer) part).Bases = bases;
995 TypeExpr[] GetNormalBases (out TypeExpr base_class)
997 base_class = null;
998 if (Bases == null)
999 return null;
1001 int count = Bases.Count;
1002 int start = 0, i, j;
1004 if (Kind == Kind.Class){
1005 TypeExpr name = ((Expression) Bases [0]).ResolveAsBaseTerminal (this, false);
1007 if (name == null){
1008 return null;
1011 if (!name.IsInterface) {
1012 // base_class could be a class, struct, enum, delegate.
1013 // This is validated in GetClassBases.
1014 base_class = name;
1015 start = 1;
1019 TypeExpr [] ifaces = new TypeExpr [count-start];
1021 for (i = start, j = 0; i < count; i++, j++){
1022 TypeExpr resolved = ((Expression) Bases [i]).ResolveAsBaseTerminal (this, false);
1023 if (resolved == null) {
1024 return null;
1027 ifaces [j] = resolved;
1030 return ifaces.Length == 0 ? null : ifaces;
1034 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
1036 ArrayList ifaces = new ArrayList (0);
1037 if (iface_exprs != null)
1038 ifaces.AddRange (iface_exprs);
1040 foreach (TypeContainer part in partial_parts) {
1041 TypeExpr new_base_class;
1042 TypeExpr[] new_ifaces = part.GetClassBases (out new_base_class);
1043 if (new_base_class != TypeManager.system_object_expr) {
1044 if (base_class == TypeManager.system_object_expr)
1045 base_class = new_base_class;
1046 else {
1047 if (new_base_class != null && !new_base_class.Equals (base_class)) {
1048 Report.SymbolRelatedToPreviousError (base_class.Location, "");
1049 Report.Error (263, part.Location,
1050 "Partial declarations of `{0}' must not specify different base classes",
1051 part.GetSignatureForError ());
1053 return null;
1058 if (new_ifaces == null)
1059 continue;
1061 foreach (TypeExpr iface in new_ifaces) {
1062 if (ifaces.Contains (iface))
1063 continue;
1065 ifaces.Add (iface);
1069 if (ifaces.Count == 0)
1070 return null;
1072 return (TypeExpr[])ifaces.ToArray (typeof (TypeExpr));
1075 /// <summary>
1076 /// This function computes the Base class and also the
1077 /// list of interfaces that the class or struct @c implements.
1078 ///
1079 /// The return value is an array (might be null) of
1080 /// interfaces implemented (as Types).
1081 ///
1082 /// The @base_class argument is set to the base object or null
1083 /// if this is `System.Object'.
1084 /// </summary>
1085 public virtual TypeExpr [] GetClassBases (out TypeExpr base_class)
1087 TypeExpr[] ifaces = GetNormalBases (out base_class);
1089 if (ifaces == null)
1090 return null;
1092 int count = ifaces.Length;
1094 for (int i = 0; i < count; i++) {
1095 TypeExpr iface = (TypeExpr) ifaces [i];
1097 if (!iface.IsInterface) {
1098 if (Kind != Kind.Class) {
1099 // TODO: location of symbol related ....
1100 Error_TypeInListIsNotInterface (Location, iface.GetSignatureForError ());
1102 else if (base_class != null)
1103 Report.Error (1721, Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1104 GetSignatureForError (), base_class.GetSignatureForError (), iface.GetSignatureForError ());
1105 else {
1106 Report.Error (1722, Location, "`{0}': Base class `{1}' must be specified as first",
1107 GetSignatureForError (), iface.GetSignatureForError ());
1109 return null;
1112 for (int x = 0; x < i; x++) {
1113 if (iface.Equals (ifaces [x])) {
1114 Report.Error (528, Location,
1115 "`{0}' is already listed in " +
1116 "interface list", iface.GetSignatureForError ());
1117 return null;
1121 if ((Kind == Kind.Interface) &&
1122 !iface.AsAccessible (Parent, ModFlags)) {
1123 Report.Error (61, Location,
1124 "Inconsistent accessibility: base " +
1125 "interface `{0}' is less accessible " +
1126 "than interface `{1}'", iface.Name,
1127 Name);
1128 return null;
1131 return ifaces;
1134 bool CheckGenericInterfaces (Type[] ifaces)
1136 #if GMCS_SOURCE
1137 ArrayList already_checked = new ArrayList ();
1139 for (int i = 0; i < ifaces.Length; i++) {
1140 Type iface = ifaces [i];
1141 foreach (Type t in already_checked) {
1142 if (iface == t)
1143 continue;
1145 Type[] inferred = new Type [CountTypeParameters];
1146 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
1147 continue;
1149 Report.Error (695, Location,
1150 "`{0}' cannot implement both `{1}' and `{2}' " +
1151 "because they may unify for some type parameter substitutions",
1152 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
1153 TypeManager.CSharpName (t));
1154 return false;
1157 already_checked.Add (iface);
1159 #endif
1161 return true;
1164 bool error = false;
1166 protected void Error_TypeInListIsNotInterface (Location loc, string type)
1168 Report.Error (527, loc, "Type `{0}' in interface list is not an interface", type);
1171 bool DefineTypeBuilder ()
1173 try {
1174 Type default_parent = null;
1175 if (Kind == Kind.Struct)
1176 default_parent = TypeManager.value_type;
1177 else if (Kind == Kind.Enum)
1178 default_parent = TypeManager.enum_type;
1180 if (IsTopLevel){
1181 if (TypeManager.NamespaceClash (Name, Location)) {
1182 return false;
1185 ModuleBuilder builder = CodeGen.Module.Builder;
1186 TypeBuilder = builder.DefineType (
1187 Name, TypeAttr, default_parent, null);
1188 } else {
1189 TypeBuilder builder = Parent.TypeBuilder;
1191 TypeBuilder = builder.DefineNestedType (
1192 Basename, TypeAttr, default_parent, null);
1194 } catch (ArgumentException) {
1195 Report.RuntimeMissingSupport (Location, "static classes");
1196 return false;
1199 TypeManager.AddUserType (this);
1201 #if GMCS_SOURCE
1202 if (IsGeneric) {
1203 string[] param_names = new string [TypeParameters.Length];
1204 for (int i = 0; i < TypeParameters.Length; i++)
1205 param_names [i] = TypeParameters [i].Name;
1207 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1209 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1210 for (int i = offset; i < gen_params.Length; i++)
1211 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1213 #endif
1215 iface_exprs = GetClassBases (out base_type);
1216 if (partial_parts != null) {
1217 iface_exprs = GetNormalPartialBases (ref base_type);
1221 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1222 // which in turn should have called DefineType()s on base types if necessary.
1224 // None of the code below should trigger DefineType()s on classes that we depend on.
1225 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1227 // Let's do it as soon as possible, since code below can call DefineType() on classes
1228 // that depend on us to be populated before they are.
1230 if (!(this is CompilerGeneratedClass))
1231 RootContext.RegisterOrder (this);
1233 if (IsGeneric && base_type != null && TypeManager.IsAttributeType (base_type.Type)) {
1234 Report.Error (698, base_type.Location,
1235 "A generic type cannot derive from `{0}' because it is an attribute class",
1236 base_type.Name);
1237 return false;
1240 if (!CheckRecursiveDefinition (this))
1241 return false;
1243 if (base_type != null) {
1244 TypeBuilder.SetParent (base_type.Type);
1246 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1247 if (obsolete_attr != null && !IsInObsoleteScope)
1248 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location);
1251 // add interfaces that were not added at type creation
1252 if (iface_exprs != null) {
1253 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1254 if (ifaces == null)
1255 return false;
1257 foreach (Type itype in ifaces)
1258 TypeBuilder.AddInterfaceImplementation (itype);
1260 foreach (TypeExpr ie in iface_exprs) {
1261 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (ie.Type);
1262 if ((oa != null) && !IsInObsoleteScope)
1263 AttributeTester.Report_ObsoleteMessage (
1264 oa, ie.GetSignatureForError (), Location);
1267 if (!CheckGenericInterfaces (ifaces))
1268 return false;
1270 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1273 return true;
1277 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1279 public override TypeBuilder DefineType ()
1281 if (TypeBuilder != null)
1282 return TypeBuilder;
1284 if (error)
1285 return null;
1287 if (!DefineTypeBuilder ()) {
1288 error = true;
1289 return null;
1292 if (partial_parts != null) {
1293 foreach (TypeContainer part in partial_parts)
1294 part.TypeBuilder = TypeBuilder;
1297 if (!(this is CompilerGeneratedClass)) {
1298 if (!ResolveMembers ()) {
1299 error = true;
1300 return null;
1304 if (!DefineNestedTypes ()) {
1305 error = true;
1306 return null;
1309 return TypeBuilder;
1312 public bool ResolveMembers ()
1314 if (members_resolved)
1315 return members_resolved_ok;
1317 members_resolved_ok = DoResolveMembers ();
1318 members_resolved = true;
1320 return members_resolved_ok;
1323 protected virtual bool DoResolveMembers ()
1325 if (methods != null) {
1326 foreach (Method method in methods) {
1327 if (!method.ResolveMembers ())
1328 return false;
1332 if (instance_constructors != null) {
1333 foreach (Constructor c in instance_constructors) {
1334 if (!c.ResolveMembers ())
1335 return false;
1339 if (default_static_constructor != null) {
1340 if (!default_static_constructor.ResolveMembers ())
1341 return false;
1344 if (operators != null) {
1345 foreach (Operator o in operators) {
1346 if (!o.ResolveMembers ())
1347 return false;
1351 if (properties != null) {
1352 foreach (PropertyBase p in properties) {
1353 if (!p.Get.IsDummy && !p.Get.ResolveMembers ())
1354 return false;
1355 if (!p.Set.IsDummy && !p.Set.ResolveMembers ())
1356 return false;
1360 if (indexers != null) {
1361 foreach (PropertyBase p in indexers) {
1362 if (!p.Get.IsDummy && !p.Get.ResolveMembers ())
1363 return false;
1364 if (!p.Set.IsDummy && !p.Set.ResolveMembers ())
1365 return false;
1369 if (events != null) {
1370 foreach (Event e in events) {
1371 if (!e.Add.ResolveMembers ())
1372 return false;
1373 if (!e.Remove.ResolveMembers ())
1374 return false;
1378 return true;
1381 Constraints [] constraints;
1382 public override void SetParameterInfo (ArrayList constraints_list)
1384 if (PartialContainer == this) {
1385 base.SetParameterInfo (constraints_list);
1386 return;
1389 if (constraints_list == null)
1390 return;
1392 constraints = new Constraints [PartialContainer.CountCurrentTypeParameters];
1394 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
1395 for (int i = 0; i < constraints.Length; i++) {
1396 foreach (Constraints constraint in constraints_list) {
1397 if (constraint.TypeParameter == current_params [i].Name) {
1398 constraints [i] = constraint;
1399 break;
1405 bool UpdateTypeParameterConstraints ()
1407 if (constraints == null)
1408 return true;
1410 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
1411 for (int i = 0; i < current_params.Length; i++) {
1412 if (!current_params [i].UpdateConstraints (this, constraints [i])) {
1413 Report.SymbolRelatedToPreviousError (Location, "");
1414 Report.Error (265, PartialContainer.Location,
1415 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1416 PartialContainer.GetSignatureForError (), current_params [i].Name);
1417 return false;
1421 return true;
1424 public bool ResolveType ()
1426 if (!DoResolveType ())
1427 return false;
1429 if (compiler_generated != null) {
1430 foreach (CompilerGeneratedClass c in compiler_generated)
1431 if (!c.ResolveType ())
1432 return false;
1435 return true;
1438 protected virtual bool DoResolveType ()
1440 if ((base_type != null) &&
1441 (base_type.ResolveAsTypeTerminal (this, false) == null)) {
1442 error = true;
1443 return false;
1446 if (!IsGeneric)
1447 return true;
1449 if (PartialContainer != this)
1450 throw new InternalErrorException ();
1452 TypeExpr current_type = null;
1454 foreach (TypeParameter type_param in CurrentTypeParameters) {
1455 if (!type_param.Resolve (this)) {
1456 error = true;
1457 return false;
1461 if (partial_parts != null) {
1462 foreach (TypeContainer part in partial_parts) {
1463 if (!part.UpdateTypeParameterConstraints ()) {
1464 error = true;
1465 return false;
1470 foreach (TypeParameter type_param in TypeParameters) {
1471 if (!type_param.DefineType (this)) {
1472 error = true;
1473 return false;
1477 current_type = new ConstructedType (TypeBuilder, TypeParameters, Location);
1479 foreach (TypeParameter type_param in TypeParameters)
1480 if (!type_param.CheckDependencies ()) {
1481 error = true;
1482 return false;
1485 if (current_type != null) {
1486 current_type = current_type.ResolveAsTypeTerminal (this, false);
1487 if (current_type == null) {
1488 error = true;
1489 return false;
1492 CurrentType = current_type.Type;
1495 return true;
1498 protected virtual bool DefineNestedTypes ()
1500 if (Interfaces != null) {
1501 foreach (TypeContainer iface in Interfaces)
1502 if (iface.DefineType () == null)
1503 return false;
1506 if (Types != null) {
1507 foreach (TypeContainer tc in Types)
1508 if (tc.DefineType () == null)
1509 return false;
1512 if (Delegates != null) {
1513 foreach (Delegate d in Delegates)
1514 if (d.DefineType () == null)
1515 return false;
1518 if (Enums != null) {
1519 foreach (Enum en in Enums)
1520 if (en.DefineType () == null)
1521 return false;
1524 if (compiler_generated != null) {
1525 foreach (CompilerGeneratedClass c in compiler_generated) {
1526 if (c.DefineType () == null)
1527 return false;
1531 return true;
1534 TypeContainer InTransit;
1536 protected bool CheckRecursiveDefinition (TypeContainer tc)
1538 if (InTransit != null) {
1539 Report.SymbolRelatedToPreviousError (this);
1540 if (this is Interface)
1541 Report.Error (
1542 529, tc.Location, "Inherited interface `{0}' causes a " +
1543 "cycle in the interface hierarchy of `{1}'",
1544 GetSignatureForError (), tc.GetSignatureForError ());
1545 else
1546 Report.Error (
1547 146, tc.Location, "Circular base class dependency " +
1548 "involving `{0}' and `{1}'",
1549 tc.GetSignatureForError (), GetSignatureForError ());
1550 return false;
1553 InTransit = tc;
1555 if (base_type != null) {
1556 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1557 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1558 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1559 return false;
1562 if (iface_exprs != null) {
1563 foreach (TypeExpr iface in iface_exprs) {
1564 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1565 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1566 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1567 return false;
1571 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1572 return false;
1574 InTransit = null;
1575 return true;
1578 public static void Error_KeywordNotAllowed (Location loc)
1580 Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
1583 /// <summary>
1584 /// Populates our TypeBuilder with fields and methods
1585 /// </summary>
1586 public override bool DefineMembers ()
1588 if (members_defined)
1589 return members_defined_ok;
1591 if (!base.DefineMembers ())
1592 return false;
1594 members_defined_ok = DoDefineMembers ();
1595 members_defined = true;
1597 return members_defined_ok;
1600 protected virtual bool DoDefineMembers ()
1602 if (iface_exprs != null) {
1603 foreach (TypeExpr iface in iface_exprs) {
1604 ConstructedType ct = iface as ConstructedType;
1605 if ((ct != null) && !ct.CheckConstraints (this))
1606 return false;
1610 if (base_type != null) {
1611 ConstructedType ct = base_type as ConstructedType;
1612 if ((ct != null) && !ct.CheckConstraints (this))
1613 return false;
1616 if (!IsTopLevel) {
1617 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1618 if (conflict_symbol == null) {
1619 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1620 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1621 } else {
1622 if ((ModFlags & Modifiers.NEW) == 0) {
1623 Report.SymbolRelatedToPreviousError (conflict_symbol);
1624 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1625 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1630 DefineContainerMembers (constants);
1631 DefineContainerMembers (fields);
1633 if (Kind == Kind.Struct || Kind == Kind.Class) {
1634 pending = PendingImplementation.GetPendingImplementations (this);
1638 // Constructors are not in the defined_names array
1640 DefineContainerMembers (instance_constructors);
1642 DefineContainerMembers (properties);
1643 DefineContainerMembers (events);
1644 DefineContainerMembers (indexers);
1645 DefineContainerMembers (methods);
1646 DefineContainerMembers (operators);
1647 DefineContainerMembers (enums);
1648 DefineContainerMembers (delegates);
1650 if (CurrentType != null) {
1651 GenericType = CurrentType;
1655 #if CACHE
1656 member_cache = new MemberCache (this);
1657 if (partial_parts != null) {
1658 foreach (TypeContainer part in partial_parts)
1659 part.member_cache = member_cache;
1661 #endif
1663 return true;
1666 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1668 if (mcal != null)
1669 mcal.DefineContainerMembers ();
1672 public override bool Define ()
1674 if (compiler_generated != null) {
1675 foreach (CompilerGeneratedClass c in compiler_generated) {
1676 if (!c.Define ())
1677 return false;
1681 return true;
1684 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1686 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1689 /// <summary>
1690 /// This function is based by a delegate to the FindMembers routine
1691 /// </summary>
1692 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1694 return true;
1697 /// <summary>
1698 /// This filter is used by FindMembers, and we just keep
1699 /// a global for the filter to `AlwaysAccept'
1700 /// </summary>
1701 static MemberFilter accepting_filter;
1704 static TypeContainer ()
1706 accepting_filter = new MemberFilter (AlwaysAccept);
1709 public MethodInfo[] GetMethods ()
1711 ArrayList members = new ArrayList ();
1713 DefineMembers ();
1715 if (methods != null) {
1716 int len = methods.Count;
1717 for (int i = 0; i < len; i++) {
1718 Method m = (Method) methods [i];
1720 members.Add (m.MethodBuilder);
1724 if (operators != null) {
1725 int len = operators.Count;
1726 for (int i = 0; i < len; i++) {
1727 Operator o = (Operator) operators [i];
1729 members.Add (o.MethodBuilder);
1733 if (properties != null) {
1734 int len = properties.Count;
1735 for (int i = 0; i < len; i++) {
1736 Property p = (Property) properties [i];
1738 if (p.GetBuilder != null)
1739 members.Add (p.GetBuilder);
1740 if (p.SetBuilder != null)
1741 members.Add (p.SetBuilder);
1745 if (indexers != null) {
1746 int len = indexers.Count;
1747 for (int i = 0; i < len; i++) {
1748 Indexer ix = (Indexer) indexers [i];
1750 if (ix.GetBuilder != null)
1751 members.Add (ix.GetBuilder);
1752 if (ix.SetBuilder != null)
1753 members.Add (ix.SetBuilder);
1757 if (events != null) {
1758 int len = events.Count;
1759 for (int i = 0; i < len; i++) {
1760 Event e = (Event) events [i];
1762 if (e.AddBuilder != null)
1763 members.Add (e.AddBuilder);
1764 if (e.RemoveBuilder != null)
1765 members.Add (e.RemoveBuilder);
1769 MethodInfo[] retMethods = new MethodInfo [members.Count];
1770 members.CopyTo (retMethods, 0);
1771 return retMethods;
1774 // Indicated whether container has StructLayout attribute set Explicit
1775 public bool HasExplicitLayout {
1776 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1777 set { caching_flags |= Flags.HasExplicitLayout; }
1781 // Return the nested type with name @name. Ensures that the nested type
1782 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1784 public Type FindNestedType (string name)
1786 if (PartialContainer != this)
1787 throw new InternalErrorException ("should not happen");
1789 ArrayList [] lists = { types, enums, delegates, interfaces };
1791 for (int j = 0; j < lists.Length; ++j) {
1792 ArrayList list = lists [j];
1793 if (list == null)
1794 continue;
1796 int len = list.Count;
1797 for (int i = 0; i < len; ++i) {
1798 DeclSpace ds = (DeclSpace) list [i];
1799 if (ds.Basename == name) {
1800 return ds.DefineType ();
1805 return null;
1808 private void FindMembers_NestedTypes (int modflags,
1809 BindingFlags bf, MemberFilter filter, object criteria,
1810 ref ArrayList members)
1812 ArrayList [] lists = { types, enums, delegates, interfaces };
1814 for (int j = 0; j < lists.Length; ++j) {
1815 ArrayList list = lists [j];
1816 if (list == null)
1817 continue;
1819 int len = list.Count;
1820 for (int i = 0; i < len; i++) {
1821 DeclSpace ds = (DeclSpace) list [i];
1823 if ((ds.ModFlags & modflags) == 0)
1824 continue;
1826 TypeBuilder tb = ds.TypeBuilder;
1827 if (tb == null) {
1828 if (!(criteria is string) || ds.Basename.Equals (criteria))
1829 tb = ds.DefineType ();
1832 if (tb != null && (filter (tb, criteria) == true)) {
1833 if (members == null)
1834 members = new ArrayList ();
1836 members.Add (tb);
1842 /// <summary>
1843 /// This method returns the members of this type just like Type.FindMembers would
1844 /// Only, we need to use this for types which are _being_ defined because MS'
1845 /// implementation can't take care of that.
1846 /// </summary>
1848 // FIXME: return an empty static array instead of null, that cleans up
1849 // some code and is consistent with some coding conventions I just found
1850 // out existed ;-)
1853 // Notice that in various cases we check if our field is non-null,
1854 // something that would normally mean that there was a bug elsewhere.
1856 // The problem happens while we are defining p-invoke methods, as those
1857 // will trigger a FindMembers, but this happens before things are defined
1859 // Since the whole process is a no-op, it is fine to check for null here.
1861 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1862 MemberFilter filter, object criteria)
1864 ArrayList members = null;
1866 int modflags = 0;
1867 if ((bf & BindingFlags.Public) != 0)
1868 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1869 Modifiers.INTERNAL;
1870 if ((bf & BindingFlags.NonPublic) != 0)
1871 modflags |= Modifiers.PRIVATE;
1873 int static_mask = 0, static_flags = 0;
1874 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1875 case BindingFlags.Static:
1876 static_mask = static_flags = Modifiers.STATIC;
1877 break;
1879 case BindingFlags.Instance:
1880 static_mask = Modifiers.STATIC;
1881 static_flags = 0;
1882 break;
1884 default:
1885 static_mask = static_flags = 0;
1886 break;
1889 Timer.StartTimer (TimerType.TcFindMembers);
1891 if (filter == null)
1892 filter = accepting_filter;
1894 if ((mt & MemberTypes.Field) != 0) {
1895 if (fields != null) {
1896 int len = fields.Count;
1897 for (int i = 0; i < len; i++) {
1898 FieldBase f = (FieldBase) fields [i];
1900 if ((f.ModFlags & modflags) == 0)
1901 continue;
1902 if ((f.ModFlags & static_mask) != static_flags)
1903 continue;
1905 FieldBuilder fb = f.FieldBuilder;
1906 if (fb != null && filter (fb, criteria) == true) {
1907 if (members == null)
1908 members = new ArrayList ();
1910 members.Add (fb);
1915 if (constants != null) {
1916 int len = constants.Count;
1917 for (int i = 0; i < len; i++) {
1918 Const con = (Const) constants [i];
1920 if ((con.ModFlags & modflags) == 0)
1921 continue;
1922 if ((con.ModFlags & static_mask) != static_flags)
1923 continue;
1925 FieldBuilder fb = con.FieldBuilder;
1926 if (fb == null) {
1927 if (con.Define ())
1928 fb = con.FieldBuilder;
1930 if (fb != null && filter (fb, criteria) == true) {
1931 if (members == null)
1932 members = new ArrayList ();
1934 members.Add (fb);
1940 if ((mt & MemberTypes.Method) != 0) {
1941 if (methods != null) {
1942 int len = methods.Count;
1943 for (int i = 0; i < len; i++) {
1944 Method m = (Method) methods [i];
1946 if ((m.ModFlags & modflags) == 0)
1947 continue;
1948 if ((m.ModFlags & static_mask) != static_flags)
1949 continue;
1951 MethodBuilder mb = m.MethodBuilder;
1953 if (mb != null && filter (mb, criteria) == true) {
1954 if (members == null)
1955 members = new ArrayList ();
1957 members.Add (mb);
1962 if (operators != null) {
1963 int len = operators.Count;
1964 for (int i = 0; i < len; i++) {
1965 Operator o = (Operator) operators [i];
1967 if ((o.ModFlags & modflags) == 0)
1968 continue;
1969 if ((o.ModFlags & static_mask) != static_flags)
1970 continue;
1972 MethodBuilder ob = o.MethodBuilder;
1973 if (ob != null && filter (ob, criteria) == true) {
1974 if (members == null)
1975 members = new ArrayList ();
1977 members.Add (ob);
1982 if (events != null) {
1983 foreach (Event e in events) {
1984 if ((e.ModFlags & modflags) == 0)
1985 continue;
1986 if ((e.ModFlags & static_mask) != static_flags)
1987 continue;
1989 MethodBuilder b = e.AddBuilder;
1990 if (b != null && filter (b, criteria)) {
1991 if (members == null)
1992 members = new ArrayList (4);
1994 members.Add (b);
1997 b = e.RemoveBuilder;
1998 if (b != null && filter (b, criteria)) {
1999 if (members == null)
2000 members = new ArrayList (4);
2002 members.Add (b);
2007 if (properties != null) {
2008 int len = properties.Count;
2009 for (int i = 0; i < len; i++) {
2010 Property p = (Property) properties [i];
2012 if ((p.ModFlags & modflags) == 0)
2013 continue;
2014 if ((p.ModFlags & static_mask) != static_flags)
2015 continue;
2017 MethodBuilder b;
2019 b = p.GetBuilder;
2020 if (b != null && filter (b, criteria) == true) {
2021 if (members == null)
2022 members = new ArrayList ();
2024 members.Add (b);
2027 b = p.SetBuilder;
2028 if (b != null && filter (b, criteria) == true) {
2029 if (members == null)
2030 members = new ArrayList ();
2032 members.Add (b);
2037 if (indexers != null) {
2038 int len = indexers.Count;
2039 for (int i = 0; i < len; i++) {
2040 Indexer ix = (Indexer) indexers [i];
2042 if ((ix.ModFlags & modflags) == 0)
2043 continue;
2044 if ((ix.ModFlags & static_mask) != static_flags)
2045 continue;
2047 MethodBuilder b;
2049 b = ix.GetBuilder;
2050 if (b != null && filter (b, criteria) == true) {
2051 if (members == null)
2052 members = new ArrayList ();
2054 members.Add (b);
2057 b = ix.SetBuilder;
2058 if (b != null && filter (b, criteria) == true) {
2059 if (members == null)
2060 members = new ArrayList ();
2062 members.Add (b);
2068 if ((mt & MemberTypes.Event) != 0) {
2069 if (events != null) {
2070 int len = events.Count;
2071 for (int i = 0; i < len; i++) {
2072 Event e = (Event) events [i];
2074 if ((e.ModFlags & modflags) == 0)
2075 continue;
2076 if ((e.ModFlags & static_mask) != static_flags)
2077 continue;
2079 MemberInfo eb = e.EventBuilder;
2080 if (eb != null && filter (eb, criteria) == true) {
2081 if (members == null)
2082 members = new ArrayList ();
2084 members.Add (e.EventBuilder);
2090 if ((mt & MemberTypes.Property) != 0){
2091 if (properties != null) {
2092 int len = properties.Count;
2093 for (int i = 0; i < len; i++) {
2094 Property p = (Property) properties [i];
2096 if ((p.ModFlags & modflags) == 0)
2097 continue;
2098 if ((p.ModFlags & static_mask) != static_flags)
2099 continue;
2101 MemberInfo pb = p.PropertyBuilder;
2102 if (pb != null && filter (pb, criteria) == true) {
2103 if (members == null)
2104 members = new ArrayList ();
2106 members.Add (p.PropertyBuilder);
2111 if (indexers != null) {
2112 int len = indexers.Count;
2113 for (int i = 0; i < len; i++) {
2114 Indexer ix = (Indexer) indexers [i];
2116 if ((ix.ModFlags & modflags) == 0)
2117 continue;
2118 if ((ix.ModFlags & static_mask) != static_flags)
2119 continue;
2121 MemberInfo ib = ix.PropertyBuilder;
2122 if (ib != null && filter (ib, criteria) == true) {
2123 if (members == null)
2124 members = new ArrayList ();
2126 members.Add (ix.PropertyBuilder);
2132 if ((mt & MemberTypes.NestedType) != 0)
2133 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
2135 if ((mt & MemberTypes.Constructor) != 0){
2136 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
2137 int len = instance_constructors.Count;
2138 for (int i = 0; i < len; i++) {
2139 Constructor c = (Constructor) instance_constructors [i];
2141 ConstructorBuilder cb = c.ConstructorBuilder;
2142 if (cb != null && filter (cb, criteria) == true) {
2143 if (members == null)
2144 members = new ArrayList ();
2146 members.Add (cb);
2151 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2152 ConstructorBuilder cb =
2153 default_static_constructor.ConstructorBuilder;
2155 if (cb != null && filter (cb, criteria) == true) {
2156 if (members == null)
2157 members = new ArrayList ();
2159 members.Add (cb);
2165 // Lookup members in base if requested.
2167 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2168 if (TypeBuilder.BaseType != null) {
2169 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2170 if (list.Count > 0) {
2171 if (members == null)
2172 members = new ArrayList ();
2174 members.AddRange (list);
2179 Timer.StopTimer (TimerType.TcFindMembers);
2181 if (members == null)
2182 return MemberList.Empty;
2183 else
2184 return new MemberList (members);
2187 public override MemberCache MemberCache {
2188 get {
2189 return member_cache;
2193 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2194 MemberFilter filter, object criteria)
2196 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2198 if (ds != null)
2199 return ds.FindMembers (mt, bf, filter, criteria);
2200 else
2201 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2204 /// <summary>
2205 /// Emits the values for the constants
2206 /// </summary>
2207 public void EmitConstants ()
2209 if (constants != null)
2210 foreach (Const con in constants)
2211 con.Emit ();
2212 return;
2215 static void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2217 if (al == null)
2218 return;
2220 foreach (MemberCore mc in al) {
2221 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2222 continue;
2224 if (!mc.IsUsed) {
2225 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2230 public virtual void VerifyMembers ()
2233 // Check for internal or private fields that were never assigned
2235 if (RootContext.WarningLevel >= 3) {
2236 CheckMemberUsage (properties, "property");
2237 CheckMemberUsage (methods, "method");
2238 CheckMemberUsage (constants, "constant");
2240 if (fields != null){
2241 foreach (FieldBase f in fields) {
2242 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2243 continue;
2245 if (!f.IsUsed){
2246 if ((f.caching_flags & Flags.IsAssigned) == 0)
2247 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2248 else {
2249 #if NET_2_0
2250 const int error_code = 414;
2251 #else
2252 const int error_code = 169;
2253 #endif
2254 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2255 f.GetSignatureForError ());
2257 continue;
2261 // Only report 649 on level 4
2263 if (RootContext.WarningLevel < 4)
2264 continue;
2266 if ((f.caching_flags & Flags.IsAssigned) != 0)
2267 continue;
2269 Constant c = New.Constantify (f.Type.Type);
2270 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2271 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2277 // TODO: move to ClassOrStruct
2278 void EmitConstructors ()
2280 if (instance_constructors == null)
2281 return;
2283 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2284 bool has_compliant_args = false;
2286 foreach (Constructor c in instance_constructors) {
2287 try {
2288 c.Emit ();
2290 catch (Exception e) {
2291 throw new InternalErrorException (c, e);
2294 if (has_compliant_args)
2295 continue;
2297 has_compliant_args = c.HasCompliantArgs;
2299 if (!has_compliant_args)
2300 Report.Error (3015, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2301 } else {
2302 foreach (Constructor c in instance_constructors) {
2303 try {
2304 c.Emit ();
2306 catch (Exception e) {
2307 throw new InternalErrorException (c, e);
2313 /// <summary>
2314 /// Emits the code, this step is performed after all
2315 /// the types, enumerations, constructors
2316 /// </summary>
2317 public virtual void EmitType ()
2319 if (OptAttributes != null)
2320 OptAttributes.Emit ();
2322 #if GMCS_SOURCE
2323 if (IsGeneric) {
2324 int offset = CountTypeParameters - CurrentTypeParameters.Length;
2325 for (int i = offset; i < gen_params.Length; i++)
2326 CurrentTypeParameters [i - offset].EmitAttributes ();
2328 #endif
2331 // Structs with no fields need to have at least one byte.
2332 // The right thing would be to set the PackingSize in a DefineType
2333 // but there are no functions that allow interfaces *and* the size to
2334 // be specified.
2337 if (Kind == Kind.Struct && first_nonstatic_field == null){
2338 FieldBuilder fb = TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
2339 FieldAttributes.Private);
2341 if (HasExplicitLayout){
2342 object [] ctor_args = new object [1];
2343 ctor_args [0] = 0;
2345 CustomAttributeBuilder cba = new CustomAttributeBuilder (
2346 TypeManager.field_offset_attribute_ctor, ctor_args);
2347 fb.SetCustomAttribute (cba);
2351 Emit ();
2353 EmitConstructors ();
2355 // Can not continue if constants are broken
2356 EmitConstants ();
2357 if (Report.Errors > 0)
2358 return;
2360 if (default_static_constructor != null)
2361 default_static_constructor.Emit ();
2363 if (methods != null){
2364 foreach (Method m in methods)
2365 m.Emit ();
2368 if (operators != null)
2369 foreach (Operator o in operators)
2370 o.Emit ();
2372 if (properties != null)
2373 foreach (Property p in properties)
2374 p.Emit ();
2376 if (indexers != null){
2377 indexers.Emit ();
2380 if (fields != null)
2381 foreach (FieldBase f in fields)
2382 f.Emit ();
2384 if (events != null){
2385 foreach (Event e in Events)
2386 e.Emit ();
2389 if (delegates != null) {
2390 foreach (Delegate d in Delegates) {
2391 d.Emit ();
2395 if (pending != null)
2396 if (pending.VerifyPendingMethods ())
2397 return;
2399 if (Report.Errors > 0)
2400 return;
2402 if (compiler_generated != null) {
2403 foreach (CompilerGeneratedClass c in compiler_generated) {
2404 if (!c.DefineMembers ())
2405 throw new InternalErrorException ();
2407 foreach (CompilerGeneratedClass c in compiler_generated)
2408 c.EmitType ();
2412 public override void CloseType ()
2414 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2415 return;
2417 try {
2418 caching_flags |= Flags.CloseTypeCreated;
2419 TypeBuilder.CreateType ();
2420 } catch (TypeLoadException){
2422 // This is fine, the code still created the type
2424 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2425 // Console.WriteLine (e.Message);
2426 } catch (Exception e) {
2427 throw new InternalErrorException (this, e);
2430 if (Enums != null)
2431 foreach (Enum en in Enums)
2432 en.CloseType ();
2434 if (Types != null){
2435 foreach (TypeContainer tc in Types)
2436 if (tc.Kind == Kind.Struct)
2437 tc.CloseType ();
2439 foreach (TypeContainer tc in Types)
2440 if (tc.Kind != Kind.Struct)
2441 tc.CloseType ();
2444 if (Delegates != null)
2445 foreach (Delegate d in Delegates)
2446 d.CloseType ();
2448 if (CompilerGenerated != null)
2449 foreach (CompilerGeneratedClass c in CompilerGenerated)
2450 c.CloseType ();
2452 types = null;
2453 properties = null;
2454 enums = null;
2455 delegates = null;
2456 fields = null;
2457 initialized_fields = null;
2458 initialized_static_fields = null;
2459 constants = null;
2460 interfaces = null;
2461 methods = null;
2462 events = null;
2463 indexers = null;
2464 operators = null;
2465 compiler_generated = null;
2466 default_constructor = null;
2467 default_static_constructor = null;
2468 type_bases = null;
2469 OptAttributes = null;
2470 ifaces = null;
2471 base_cache = null;
2472 member_cache = null;
2476 // Performs the validation on a Method's modifiers (properties have
2477 // the same properties).
2479 public bool MethodModifiersValid (MemberCore mc)
2481 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2482 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2483 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2484 bool ok = true;
2485 int flags = mc.ModFlags;
2488 // At most one of static, virtual or override
2490 if ((flags & Modifiers.STATIC) != 0){
2491 if ((flags & vao) != 0){
2492 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2493 mc.GetSignatureForError ());
2494 ok = false;
2498 if (Kind == Kind.Struct){
2499 if ((flags & va) != 0){
2500 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2501 ok = false;
2505 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2506 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2507 mc.GetSignatureForError ());
2508 ok = false;
2512 // If the declaration includes the abstract modifier, then the
2513 // declaration does not include static, virtual or extern
2515 if ((flags & Modifiers.ABSTRACT) != 0){
2516 if ((flags & Modifiers.EXTERN) != 0){
2517 Report.Error (
2518 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2519 ok = false;
2522 if ((flags & Modifiers.SEALED) != 0) {
2523 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2524 ok = false;
2527 if ((flags & Modifiers.VIRTUAL) != 0){
2528 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2529 ok = false;
2532 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2533 Report.SymbolRelatedToPreviousError (this);
2534 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2535 mc.GetSignatureForError (), GetSignatureForError ());
2536 ok = false;
2540 if ((flags & Modifiers.PRIVATE) != 0){
2541 if ((flags & vao) != 0){
2542 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2543 ok = false;
2547 if ((flags & Modifiers.SEALED) != 0){
2548 if ((flags & Modifiers.OVERRIDE) == 0){
2549 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2550 ok = false;
2554 return ok;
2557 public Constructor DefaultStaticConstructor {
2558 get { return default_static_constructor; }
2561 protected override bool VerifyClsCompliance ()
2563 if (!base.VerifyClsCompliance ())
2564 return false;
2566 VerifyClsName ();
2568 Type base_type = TypeBuilder.BaseType;
2569 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2570 Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2572 return true;
2576 /// <summary>
2577 /// Checks whether container name is CLS Compliant
2578 /// </summary>
2579 void VerifyClsName ()
2581 Hashtable base_members = base_cache == null ?
2582 new Hashtable () :
2583 base_cache.GetPublicMembers ();
2584 Hashtable this_members = new Hashtable ();
2586 foreach (DictionaryEntry entry in defined_names) {
2587 MemberCore mc = (MemberCore)entry.Value;
2588 if (!mc.IsClsComplianceRequired ())
2589 continue;
2591 string name = (string) entry.Key;
2592 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2594 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2595 object found = base_members [lcase];
2596 if (found == null) {
2597 found = this_members [lcase];
2598 if (found == null) {
2599 this_members.Add (lcase, mc);
2600 continue;
2604 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2605 continue;
2607 if (found is MemberInfo) {
2608 if (basename == ((MemberInfo) found).Name)
2609 continue;
2610 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2611 } else {
2612 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2614 #if GMCS_SOURCE
2615 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2616 #else
2617 Report.Error (3005, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2618 #endif
2623 /// <summary>
2624 /// Performs checks for an explicit interface implementation. First it
2625 /// checks whether the `interface_type' is a base inteface implementation.
2626 /// Then it checks whether `name' exists in the interface type.
2627 /// </summary>
2628 public virtual bool VerifyImplements (InterfaceMemberBase mb)
2630 if (ifaces != null) {
2631 foreach (Type t in ifaces){
2632 if (t == mb.InterfaceType)
2633 return true;
2637 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2638 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2639 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2640 return false;
2643 public override Type LookupAnyGeneric (string typeName)
2645 if (types != null) {
2646 foreach (TypeContainer tc in types) {
2647 if (!tc.IsGeneric)
2648 continue;
2650 int pos = tc.Basename.LastIndexOf ('`');
2651 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2652 return tc.TypeBuilder;
2656 return base.LookupAnyGeneric (typeName);
2659 public void Mark_HasEquals ()
2661 Methods.HasEquals = true;
2664 public void Mark_HasGetHashCode ()
2666 Methods.HasGetHashCode = true;
2670 // IMemberContainer
2673 string IMemberContainer.Name {
2674 get {
2675 return Name;
2679 Type IMemberContainer.Type {
2680 get {
2681 return TypeBuilder;
2685 MemberCache IMemberContainer.MemberCache {
2686 get {
2687 return member_cache;
2691 bool IMemberContainer.IsInterface {
2692 get {
2693 return Kind == Kind.Interface;
2697 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2699 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2701 if (GenericType != null)
2702 return TypeManager.FindMembers (GenericType, mt, new_bf,
2703 null, null);
2704 else
2705 return FindMembers (mt, new_bf, null, null);
2709 // Generates xml doc comments (if any), and if required,
2710 // handle warning report.
2712 internal override void GenerateDocComment (DeclSpace ds)
2714 DocUtil.GenerateTypeDocComment (this, ds);
2717 public override string DocCommentHeader {
2718 get { return "T:"; }
2721 public virtual MemberCache BaseCache {
2722 get {
2723 if (base_cache != null)
2724 return base_cache;
2725 if (TypeBuilder.BaseType != null)
2726 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2727 if (TypeBuilder.IsInterface)
2728 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2729 return base_cache;
2734 public abstract class ClassOrStruct : TypeContainer {
2735 ListDictionary declarative_security;
2737 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2738 MemberName name, Attributes attrs, Kind kind)
2739 : base (ns, parent, name, attrs, kind)
2743 protected override bool AddToContainer (MemberCore symbol, string name)
2745 if (name == MemberName.Name) {
2746 if (symbol is TypeParameter) {
2747 Report.Error (694, symbol.Location,
2748 "Type parameter `{0}' has same name as " +
2749 "containing type, or method", name);
2750 return false;
2753 Report.SymbolRelatedToPreviousError (this);
2754 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2755 symbol.GetSignatureForError ());
2756 return false;
2759 return base.AddToContainer (symbol, name);
2762 public override void VerifyMembers ()
2764 base.VerifyMembers ();
2766 if ((events != null) && (RootContext.WarningLevel >= 3)) {
2767 foreach (Event e in events){
2768 if ((e.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2769 continue;
2771 if ((e.caching_flags & Flags.IsUsed) == 0)
2772 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2777 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2779 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2780 if (declarative_security == null)
2781 declarative_security = new ListDictionary ();
2783 a.ExtractSecurityPermissionSet (declarative_security);
2784 return;
2787 if (a.Type == TypeManager.struct_layout_attribute_type && a.GetLayoutKindValue () == LayoutKind.Explicit) {
2788 HasExplicitLayout = true;
2791 base.ApplyAttributeBuilder (a, cb);
2794 /// <summary>
2795 /// Defines the default constructors
2796 /// </summary>
2797 protected void DefineDefaultConstructor (bool is_static)
2799 // The default instance constructor is public
2800 // If the class is abstract, the default constructor is protected
2801 // The default static constructor is private
2803 int mods;
2804 if (is_static) {
2805 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2806 } else {
2807 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2810 Constructor c = new Constructor (this, MemberName.Name, mods,
2811 Parameters.EmptyReadOnlyParameters,
2812 new GeneratedBaseInitializer (Location),
2813 Location);
2815 AddConstructor (c);
2816 c.Block = new ToplevelBlock (null, Location);
2819 void DefineFieldInitializers ()
2821 if (initialized_fields != null) {
2822 for (int i = 0; i < initialized_fields.Count; ++i) {
2823 FieldInitializer fi = (FieldInitializer)initialized_fields[i];
2825 EmitContext ec = new EmitContext (fi.TypeContainer, fi.TypeContainer,
2826 Location, null, null, ModFlags);
2827 ec.IsFieldInitializer = true;
2829 fi.ResolveStatement (ec);
2830 if (fi.IsDefaultInitializer && RootContext.Optimize) {
2831 // Field is re-initialized to its default value => removed
2832 initialized_fields.RemoveAt (i);
2833 --i;
2838 if (initialized_static_fields != null) {
2839 bool has_complex_initializer = false;
2841 foreach (FieldInitializer fi in initialized_static_fields) {
2842 EmitContext ec = new EmitContext (fi.TypeContainer, fi.TypeContainer,
2843 Location, null, null, ModFlags);
2844 ec.IsStatic = true;
2845 ec.IsFieldInitializer = true;
2847 fi.ResolveStatement (ec);
2848 if (!fi.IsComplexInitializer)
2849 continue;
2851 has_complex_initializer = true;
2854 // Need special check to not optimize code like this
2855 // static int a = b = 5;
2856 // static int b = 0;
2857 if (!has_complex_initializer && RootContext.Optimize) {
2858 for (int i = 0; i < initialized_static_fields.Count; ++i) {
2859 FieldInitializer fi = (FieldInitializer)initialized_static_fields[i];
2860 if (fi.IsDefaultInitializer) {
2861 initialized_static_fields.RemoveAt (i);
2862 --i;
2867 if (default_static_constructor == null && initialized_static_fields.Count > 0) {
2868 DefineDefaultConstructor (true);
2874 public override bool Define ()
2876 DefineFieldInitializers ();
2878 if (default_static_constructor != null)
2879 default_static_constructor.Define ();
2881 return base.Define ();
2884 public override void Emit ()
2886 base.Emit ();
2888 if (declarative_security != null) {
2889 foreach (DictionaryEntry de in declarative_security) {
2890 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2895 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name)
2897 return NamespaceEntry.LookupExtensionMethod (extensionType, true, name);
2900 protected override TypeAttributes TypeAttr {
2901 get {
2902 if (default_static_constructor == null)
2903 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2905 return base.TypeAttr;
2911 // TODO: should be sealed
2912 public class Class : ClassOrStruct {
2913 const int AllowedModifiers =
2914 Modifiers.NEW |
2915 Modifiers.PUBLIC |
2916 Modifiers.PROTECTED |
2917 Modifiers.INTERNAL |
2918 Modifiers.PRIVATE |
2919 Modifiers.ABSTRACT |
2920 Modifiers.SEALED |
2921 Modifiers.STATIC |
2922 Modifiers.UNSAFE;
2924 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2926 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
2927 Attributes attrs)
2928 : base (ns, parent, name, attrs, Kind.Class)
2930 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2931 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2933 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2934 Report.FeatureIsNotISO1 (Location, "static classes");
2938 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2940 if (a.Type == TypeManager.attribute_usage_type) {
2941 if (BaseType != TypeManager.attribute_type && !BaseType.IsSubclassOf (TypeManager.attribute_type) &&
2942 TypeBuilder.FullName != "System.Attribute") {
2943 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2947 if (a.Type == TypeManager.conditional_attribute_type &&
2948 !(BaseType == TypeManager.attribute_type || BaseType.IsSubclassOf (TypeManager.attribute_type))) {
2949 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2950 return;
2953 if (a.Type == TypeManager.comimport_attr_type &&
2954 !attributes.Contains (TypeManager.guid_attr_type)) {
2955 a.Error_MissingGuidAttribute ();
2956 return;
2959 if (a.Type == TypeManager.extension_attribute_type) {
2960 a.Error_MisusedExtensionAttribute ();
2961 return;
2964 if (AttributeTester.IsAttributeExcluded (a.Type))
2965 return;
2967 base.ApplyAttributeBuilder (a, cb);
2970 public override AttributeTargets AttributeTargets {
2971 get {
2972 return AttributeTargets.Class;
2976 protected override void DefineContainerMembers (MemberCoreArrayList list)
2978 if (list == null)
2979 return;
2981 if (!IsStatic) {
2982 base.DefineContainerMembers (list);
2983 return;
2986 foreach (MemberCore m in list) {
2987 if (m is Operator) {
2988 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2989 continue;
2992 if (m is Destructor) {
2993 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2994 continue;
2997 if ((m.ModFlags & Modifiers.PROTECTED) != 0) {
2998 Report.Error (1057, m.Location, "`{0}': Static classes cannot contain protected members", m.GetSignatureForError ());
2999 continue;
3002 if (m is Indexer) {
3003 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
3004 continue;
3007 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
3008 continue;
3010 if (m is Constructor) {
3011 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
3012 continue;
3015 Method method = m as Method;
3016 if (method != null && method.Parameters.HasExtensionMethodType) {
3017 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
3018 continue;
3021 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
3024 base.DefineContainerMembers (list);
3027 public override TypeBuilder DefineType ()
3029 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
3030 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
3031 return null;
3034 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
3035 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
3036 return null;
3039 return base.DefineType ();
3042 protected override bool DoDefineMembers ()
3044 if (InstanceConstructors == null && !IsStatic)
3045 DefineDefaultConstructor (false);
3047 return base.DoDefineMembers ();
3050 public override void Emit ()
3052 base.Emit ();
3054 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
3055 TypeBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
3058 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
3060 TypeExpr[] ifaces = base.GetClassBases (out base_class);
3062 if (base_class == null) {
3063 if (RootContext.StdLib)
3064 base_class = TypeManager.system_object_expr;
3065 else if (Name != "System.Object")
3066 base_class = TypeManager.system_object_expr;
3067 } else {
3068 if (Kind == Kind.Class && base_class is TypeParameterExpr){
3069 Report.Error (
3070 689, base_class.Location,
3071 "Cannot derive from `{0}' because it is a type parameter",
3072 base_class.GetSignatureForError ());
3073 return ifaces;
3076 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
3077 Report.Error (1521, base_class.Location, "Invalid base type");
3078 return ifaces;
3081 if (base_class.IsSealed){
3082 Report.SymbolRelatedToPreviousError (base_class.Type);
3083 if (base_class.Type.IsAbstract) {
3084 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
3085 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
3086 } else {
3087 Report.Error (509, Location, "`{0}': cannot derive from sealed class `{1}'",
3088 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
3090 return ifaces;
3093 if (!base_class.CanInheritFrom ()){
3094 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
3095 GetSignatureForError (), base_class.GetSignatureForError ());
3096 return ifaces;
3099 if (!base_class.AsAccessible (this, ModFlags)) {
3100 Report.SymbolRelatedToPreviousError (base_class.Type);
3101 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
3102 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
3106 if (IsStatic) {
3107 if (base_class != TypeManager.system_object_expr) {
3108 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
3109 GetSignatureForError (), base_class.GetSignatureForError ());
3110 return ifaces;
3113 if (ifaces != null) {
3114 foreach (TypeExpr t in ifaces)
3115 Report.SymbolRelatedToPreviousError (t.Type);
3116 Report.Error (714, Location, "`{0}': static classes cannot implement interfaces", GetSignatureForError ());
3120 return ifaces;
3123 /// Search for at least one defined condition in ConditionalAttribute of attribute class
3124 /// Valid only for attribute classes.
3125 public bool IsExcluded ()
3127 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3128 return (caching_flags & Flags.Excluded) != 0;
3130 caching_flags &= ~Flags.Excluded_Undetected;
3132 if (OptAttributes == null)
3133 return false;
3135 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
3137 if (attrs == null)
3138 return false;
3140 foreach (Attribute a in attrs) {
3141 string condition = a.GetConditionalAttributeValue ();
3142 if (RootContext.AllDefines.Contains (condition))
3143 return false;
3146 caching_flags |= Flags.Excluded;
3147 return true;
3150 bool IsStatic {
3151 get {
3152 return (ModFlags & Modifiers.STATIC) != 0;
3157 // FIXME: How do we deal with the user specifying a different
3158 // layout?
3160 protected override TypeAttributes TypeAttr {
3161 get {
3162 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
3163 if (IsStatic)
3164 ta |= StaticClassAttribute;
3165 return ta;
3170 public sealed class Struct : ClassOrStruct {
3171 // <summary>
3172 // Modifiers allowed in a struct declaration
3173 // </summary>
3174 const int AllowedModifiers =
3175 Modifiers.NEW |
3176 Modifiers.PUBLIC |
3177 Modifiers.PROTECTED |
3178 Modifiers.INTERNAL |
3179 Modifiers.UNSAFE |
3180 Modifiers.PRIVATE;
3182 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
3183 int mod, Attributes attrs)
3184 : base (ns, parent, name, attrs, Kind.Struct)
3186 int accmods;
3188 if (parent.Parent == null)
3189 accmods = Modifiers.INTERNAL;
3190 else
3191 accmods = Modifiers.PRIVATE;
3193 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
3195 this.ModFlags |= Modifiers.SEALED;
3198 public override AttributeTargets AttributeTargets {
3199 get {
3200 return AttributeTargets.Struct;
3204 const TypeAttributes DefaultTypeAttributes =
3205 TypeAttributes.SequentialLayout |
3206 TypeAttributes.Sealed |
3207 TypeAttributes.BeforeFieldInit;
3210 public override TypeExpr[] GetClassBases (out TypeExpr base_class)
3212 TypeExpr[] ifaces = base.GetClassBases (out base_class);
3214 // If we are compiling our runtime,
3215 // and we are defining ValueType, then our
3216 // base is `System.Object'.
3218 if (base_class == null) {
3219 if (!RootContext.StdLib && Name == "System.ValueType")
3220 base_class = TypeManager.system_object_expr;
3221 else
3222 base_class = TypeManager.system_valuetype_expr;
3225 return ifaces;
3229 // FIXME: Allow the user to specify a different set of attributes
3230 // in some cases (Sealed for example is mandatory for a class,
3231 // but what SequentialLayout can be changed
3233 protected override TypeAttributes TypeAttr {
3234 get {
3235 return base.TypeAttr | DefaultTypeAttributes;
3239 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3241 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3242 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3243 field.GetSignatureForError ());
3244 return;
3246 base.RegisterFieldForInitialization (field, expression);
3251 /// <summary>
3252 /// Interfaces
3253 /// </summary>
3254 public sealed class Interface : TypeContainer, IMemberContainer {
3256 /// <summary>
3257 /// Modifiers allowed in a class declaration
3258 /// </summary>
3259 public const int AllowedModifiers =
3260 Modifiers.NEW |
3261 Modifiers.PUBLIC |
3262 Modifiers.PROTECTED |
3263 Modifiers.INTERNAL |
3264 Modifiers.UNSAFE |
3265 Modifiers.PRIVATE;
3267 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, int mod,
3268 Attributes attrs)
3269 : base (ns, parent, name, attrs, Kind.Interface)
3271 int accmods;
3273 if (parent.Parent == null)
3274 accmods = Modifiers.INTERNAL;
3275 else
3276 accmods = Modifiers.PRIVATE;
3278 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
3281 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3283 if (a.Type == TypeManager.comimport_attr_type &&
3284 !attributes.Contains (TypeManager.guid_attr_type)) {
3285 a.Error_MissingGuidAttribute ();
3286 return;
3288 base.ApplyAttributeBuilder (a, cb);
3292 public override AttributeTargets AttributeTargets {
3293 get {
3294 return AttributeTargets.Interface;
3298 const TypeAttributes DefaultTypeAttributes =
3299 TypeAttributes.AutoLayout |
3300 TypeAttributes.Abstract |
3301 TypeAttributes.Interface;
3303 protected override TypeAttributes TypeAttr {
3304 get {
3305 return base.TypeAttr | DefaultTypeAttributes;
3309 protected override bool VerifyClsCompliance ()
3311 if (!base.VerifyClsCompliance ())
3312 return false;
3314 if (ifaces != null) {
3315 foreach (Type t in ifaces) {
3316 if (AttributeTester.IsClsCompliant (t))
3317 continue;
3319 Report.SymbolRelatedToPreviousError (t);
3320 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3321 GetSignatureForError (), TypeManager.CSharpName (t));
3325 return true;
3329 // It is used as a base class for all property based members
3330 // This includes properties, indexers, and events
3331 public abstract class PropertyBasedMember : InterfaceMemberBase
3333 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3334 Expression type, int mod, int allowed_mod, bool is_iface,
3335 MemberName name, Attributes attrs)
3336 : base (parent, generic, type, mod, allowed_mod, is_iface, name, attrs)
3340 protected override bool CheckForDuplications ()
3342 throw new NotSupportedException ();
3345 protected override bool VerifyClsCompliance ()
3347 if (!base.VerifyClsCompliance ())
3348 return false;
3350 if (!AttributeTester.IsClsCompliant (MemberType)) {
3351 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3352 GetSignatureForError ());
3354 return true;
3360 public abstract class MethodCore : InterfaceMemberBase
3362 public readonly Parameters Parameters;
3363 protected ToplevelBlock block;
3365 public MethodCore (DeclSpace parent, GenericMethod generic,
3366 Expression type, int mod, int allowed_mod, bool is_iface,
3367 MemberName name, Attributes attrs, Parameters parameters)
3368 : base (parent, generic, type, mod, allowed_mod, is_iface, name, attrs)
3370 Parameters = parameters;
3374 // Returns the System.Type array for the parameters of this method
3376 public Type [] ParameterTypes {
3377 get {
3378 return Parameters.Types;
3382 public Parameters ParameterInfo
3384 get {
3385 return Parameters;
3389 public ToplevelBlock Block {
3390 get {
3391 return block;
3394 set {
3395 block = value;
3399 protected override bool CheckBase ()
3401 // Check whether arguments were correct.
3402 if (!DefineParameters (Parameters))
3403 return false;
3405 if (!base.CheckBase ())
3406 return false;
3408 return true;
3411 // TODO: create a special method for operators only to make code better
3412 protected bool IsDuplicateImplementation (MethodCore method)
3414 if (method == this)
3415 return false;
3417 Operator op2 = null;
3418 Operator op1 = null;
3420 if (!(method.MemberName.Equals (MemberName)))
3422 op1 = this as Operator;
3423 if (op1 == null || !(op1.OperatorType == Operator.OpType.Explicit || op1.OperatorType == Operator.OpType.Implicit))
3424 return false;
3426 op2 = method as Operator;
3427 if (op2 == null || !(op2.OperatorType == Operator.OpType.Explicit || op2.OperatorType == Operator.OpType.Implicit))
3428 return false;
3429 } else {
3430 op1 = this as Operator;
3431 op2 = method as Operator;
3434 Type[] param_types = method.ParameterTypes;
3435 // This never happen. Rewrite this as Equal
3436 if (param_types == null && ParameterTypes == null)
3437 return true;
3438 if (param_types == null || ParameterTypes == null)
3439 return false;
3441 if (param_types.Length != ParameterTypes.Length)
3442 return false;
3444 if (method.Parameters.HasArglist != Parameters.HasArglist)
3445 return false;
3447 bool equal = true;
3449 for (int i = 0; i < param_types.Length; i++) {
3450 if (param_types [i] != ParameterTypes [i])
3451 equal = false;
3454 if (IsExplicitImpl && (method.InterfaceType != InterfaceType))
3455 equal = false;
3457 // TODO: make operator compatible with MethodCore to avoid this
3458 if (op1 != null && op2 != null) {
3459 if (MemberType != method.MemberType)
3460 equal = false;
3463 if (equal) {
3465 // Try to report 663: method only differs on out/ref
3467 Parameters info = ParameterInfo;
3468 Parameters other_info = method.ParameterInfo;
3469 for (int i = 0; i < info.Count; i++){
3470 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3471 Report.SymbolRelatedToPreviousError (method);
3472 Report.Error (663, Location, "`{0}': Methods cannot differ only on their use of ref and out on a parameters",
3473 GetSignatureForError ());
3474 return false;
3478 Report.SymbolRelatedToPreviousError (method);
3479 if (this is Operator && method is Operator)
3480 Report.Error (557, Location, "Duplicate user-defined conversion in type `{0}'", Parent.Name);
3481 else
3482 Report.Error (111, Location, TypeContainer.Error111, GetSignatureForError ());
3484 return true;
3487 return false;
3491 // Returns a string that represents the signature for this
3492 // member which should be used in XML documentation.
3494 public override string GetDocCommentName (DeclSpace ds)
3496 return DocUtil.GetMethodDocCommentName (this, Parameters, ds);
3500 // Raised (and passed an XmlElement that contains the comment)
3501 // when GenerateDocComment is writing documentation expectedly.
3503 // FIXME: with a few effort, it could be done with XmlReader,
3504 // that means removal of DOM use.
3506 internal override void OnGenerateDocComment (XmlElement el)
3508 DocUtil.OnMethodGenerateDocComment (this, el);
3512 // Represents header string for documentation comment.
3514 public override string DocCommentHeader
3516 get { return "M:"; }
3519 public virtual void SetYields ()
3521 ModFlags |= Modifiers.METHOD_YIELDS;
3524 protected override bool VerifyClsCompliance ()
3526 if (!base.VerifyClsCompliance ())
3527 return false;
3529 if (Parameters.HasArglist) {
3530 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3533 if (!AttributeTester.IsClsCompliant (MemberType)) {
3534 Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant",
3535 GetSignatureForError ());
3538 Parameters.VerifyClsCompliance ();
3539 return true;
3544 public abstract class InterfaceMemberBase : MemberBase {
3546 // Whether this is an interface member.
3548 public bool IsInterface;
3551 // If true, this is an explicit interface implementation
3553 public bool IsExplicitImpl;
3555 protected bool is_external_implementation;
3558 // The interface type we are explicitly implementing
3560 public Type InterfaceType;
3563 // The method we're overriding if this is an override method.
3565 protected MethodInfo base_method;
3567 readonly int explicit_mod_flags;
3568 public MethodAttributes flags;
3570 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3571 Expression type, int mod, int allowed_mod, bool is_iface,
3572 MemberName name, Attributes attrs)
3573 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3574 name, attrs)
3576 IsInterface = is_iface;
3577 IsExplicitImpl = (MemberName.Left != null);
3578 explicit_mod_flags = mod;
3581 protected override bool CheckBase ()
3583 if (!base.CheckBase ())
3584 return false;
3586 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
3587 return false;
3589 if (IsExplicitImpl)
3590 return true;
3592 // Is null for System.Object while compiling corlib and base interfaces
3593 if (Parent.PartialContainer.BaseCache == null) {
3594 if ((ModFlags & Modifiers.NEW) != 0) {
3595 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3597 return true;
3600 Type base_ret_type = null;
3601 base_method = FindOutBaseMethod (ref base_ret_type);
3603 // method is override
3604 if (base_method != null) {
3605 if (!CheckMethodAgainstBase (base_ret_type))
3606 return false;
3608 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3609 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3610 if (oa != null) {
3611 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type)) {
3612 Report.SymbolRelatedToPreviousError (base_method);
3613 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3614 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3616 } else {
3617 if (OptAttributes != null && OptAttributes.Contains (TypeManager.obsolete_attribute_type)) {
3618 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3619 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3623 return true;
3626 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3627 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3628 if (conflict_symbol != null) {
3629 Report.SymbolRelatedToPreviousError (conflict_symbol);
3630 if (this is Event)
3631 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3632 else if (this is PropertyBase)
3633 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3634 else
3635 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3636 } else {
3637 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3638 GetSignatureForError (), SimpleName.GetMemberType (this));
3640 return false;
3643 if (conflict_symbol == null) {
3644 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3645 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3647 return true;
3650 if ((ModFlags & Modifiers.NEW) == 0) {
3651 if (this is Method && conflict_symbol is MethodBase)
3652 return true;
3654 Report.SymbolRelatedToPreviousError (conflict_symbol);
3655 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3656 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3659 return true;
3663 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3664 // that have been defined.
3666 // `name' is the user visible name for reporting errors (this is used to
3667 // provide the right name regarding method names and properties)
3669 bool CheckMethodAgainstBase (Type baseMethodType)
3671 bool ok = true;
3673 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3674 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3675 Report.Error (506, Location,
3676 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3677 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3678 ok = false;
3681 // Now we check that the overriden method is not final
3683 if (base_method.IsFinal) {
3684 Report.SymbolRelatedToPreviousError (base_method);
3685 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3686 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3687 ok = false;
3690 // Check that the permissions are not being changed
3692 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3693 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3695 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3696 Error_CannotChangeAccessModifiers (base_method, base_classp, null);
3697 ok = false;
3700 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (baseMethodType))) {
3701 Report.SymbolRelatedToPreviousError (base_method);
3702 if (this is PropertyBasedMember) {
3703 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3704 GetSignatureForError (), TypeManager.CSharpName (baseMethodType), TypeManager.CSharpSignature (base_method));
3706 else {
3707 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3708 GetSignatureForError (), TypeManager.CSharpName (baseMethodType), TypeManager.CSharpSignature (base_method));
3710 ok = false;
3714 if ((ModFlags & Modifiers.NEW) == 0) {
3715 if ((ModFlags & Modifiers.OVERRIDE) == 0 && Name != "Finalize") {
3716 ModFlags |= Modifiers.NEW;
3717 Report.SymbolRelatedToPreviousError (base_method);
3718 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3719 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",
3720 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3721 } else {
3722 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3723 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3726 } else {
3727 if (base_method.IsAbstract && !IsInterface) {
3728 Report.SymbolRelatedToPreviousError (base_method);
3729 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3730 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3731 return ok = false;
3735 return ok;
3738 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3740 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3742 // when overriding protected internal, the method can be declared
3743 // protected internal only within the same assembly
3746 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3747 if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3749 // assemblies differ - report an error
3752 return false;
3753 } else if (thisp != base_classp) {
3755 // same assembly, but other attributes differ - report an error
3758 return false;
3760 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3762 // if it's not "protected internal", it must be "protected"
3765 return false;
3766 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3768 // protected within the same assembly - an error
3770 return false;
3771 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3772 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3774 // protected ok, but other attributes differ - report an error
3776 return false;
3778 return true;
3779 } else {
3780 return (thisp == base_classp);
3784 public bool CheckAbstractAndExtern (bool has_block)
3786 if (Parent.PartialContainer.Kind == Kind.Interface)
3787 return true;
3789 if (has_block) {
3790 if ((ModFlags & Modifiers.EXTERN) != 0) {
3791 Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
3792 GetSignatureForError ());
3793 return false;
3796 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
3797 Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
3798 GetSignatureForError ());
3799 return false;
3801 } else {
3802 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
3803 Report.Error (501, Location, "`{0}' must declare a body because it is not marked abstract or extern",
3804 GetSignatureForError ());
3805 return false;
3809 return true;
3812 protected bool DefineParameters (Parameters parameters)
3814 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
3816 if (!parameters.Resolve (rc))
3817 return false;
3819 bool error = false;
3820 foreach (Parameter p in parameters.FixedParameters) {
3821 if (p.CheckAccessibility (this))
3822 continue;
3824 Report.SymbolRelatedToPreviousError (p.ParameterType);
3825 if (this is Indexer)
3826 Report.Error (55, Location,
3827 "Inconsistent accessibility: parameter type `" +
3828 TypeManager.CSharpName (p.ParameterType) + "' is less " +
3829 "accessible than indexer `" + GetSignatureForError () + "'");
3830 else if (this is Operator)
3831 Report.Error (57, Location,
3832 "Inconsistent accessibility: parameter type `" +
3833 TypeManager.CSharpName (p.ParameterType) + "' is less " +
3834 "accessible than operator `" + GetSignatureForError () + "'");
3835 else
3836 Report.Error (51, Location,
3837 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3838 TypeManager.CSharpName (p.ParameterType), GetSignatureForError ());
3839 error = true;
3841 return !error;
3844 protected override bool DoDefine()
3846 if (!base.DoDefine ())
3847 return false;
3849 if (IsExplicitImpl) {
3850 Expression expr = MemberName.Left.GetTypeExpression ();
3851 TypeExpr texpr = expr.ResolveAsTypeTerminal (this, false);
3852 if (texpr == null)
3853 return false;
3855 InterfaceType = texpr.Type;
3857 if (!InterfaceType.IsInterface) {
3858 Report.Error (538, Location, "`{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
3859 return false;
3862 if (!Parent.PartialContainer.VerifyImplements (this))
3863 return false;
3866 return true;
3869 protected virtual bool DoDefineBase ()
3871 if (Name == null)
3872 throw new InternalErrorException ();
3874 if (IsInterface) {
3875 ModFlags = Modifiers.PUBLIC |
3876 Modifiers.ABSTRACT |
3877 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
3879 flags = MethodAttributes.Public |
3880 MethodAttributes.Abstract |
3881 MethodAttributes.HideBySig |
3882 MethodAttributes.NewSlot |
3883 MethodAttributes.Virtual;
3884 } else {
3885 if (!Parent.PartialContainer.MethodModifiersValid (this))
3886 return false;
3888 flags = Modifiers.MethodAttr (ModFlags);
3891 if (IsExplicitImpl) {
3892 Expression expr = MemberName.Left.GetTypeExpression ();
3893 TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (this, false);
3894 if (iface_texpr == null)
3895 return false;
3897 InterfaceType = iface_texpr.Type;
3899 if (!InterfaceType.IsInterface) {
3900 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
3901 return false;
3904 if (!Parent.PartialContainer.VerifyImplements (this))
3905 return false;
3907 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
3910 return true;
3913 public override void Emit()
3915 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3916 // We are more strict than Microsoft and report CS0626 as error
3917 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3918 Report.Error (626, Location,
3919 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3920 GetSignatureForError ());
3923 base.Emit ();
3926 protected void Error_CannotChangeAccessModifiers (MemberInfo base_method, MethodAttributes ma, string suffix)
3928 Report.SymbolRelatedToPreviousError (base_method);
3929 string base_name = TypeManager.GetFullNameSignature (base_method);
3930 string this_name = GetSignatureForError ();
3931 if (suffix != null) {
3932 base_name += suffix;
3933 this_name += suffix;
3936 Report.Error (507, Location, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3937 this_name, Modifiers.GetDescription (ma), base_name);
3940 protected static string Error722 {
3941 get {
3942 return "`{0}': static types cannot be used as return types";
3946 /// <summary>
3947 /// For custom member duplication search in a container
3948 /// </summary>
3949 protected abstract bool CheckForDuplications ();
3951 /// <summary>
3952 /// Gets base method and its return type
3953 /// </summary>
3954 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3957 // The "short" name of this property / indexer / event. This is the
3958 // name without the explicit interface.
3960 public string ShortName
3962 get { return MemberName.Name; }
3963 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3966 protected override bool VerifyClsCompliance ()
3968 if (!base.VerifyClsCompliance ()) {
3969 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3970 Report.Error (3010, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3973 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3974 Report.Error (3011, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3976 return false;
3979 if (GenericMethod != null)
3980 GenericMethod.VerifyClsCompliance ();
3982 return true;
3985 public override bool IsUsed
3987 get { return IsExplicitImpl || base.IsUsed; }
3992 public abstract class MethodOrOperator : MethodCore, IMethodData
3994 public MethodBuilder MethodBuilder;
3995 ReturnParameter return_attributes;
3996 ListDictionary declarative_security;
3997 protected MethodData MethodData;
3999 Iterator iterator;
4000 ArrayList anonymous_methods;
4002 static string[] attribute_targets = new string [] { "method", "return" };
4004 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, Expression type, int mod,
4005 int allowed_mod, bool is_interface, MemberName name,
4006 Attributes attrs, Parameters parameters)
4007 : base (parent, generic, type, mod, allowed_mod, is_interface, name,
4008 attrs, parameters)
4012 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4014 if (a.Target == AttributeTargets.ReturnValue) {
4015 if (return_attributes == null)
4016 return_attributes = new ReturnParameter (MethodBuilder, Location);
4018 return_attributes.ApplyAttributeBuilder (a, cb);
4019 return;
4022 if (a.IsInternalMethodImplAttribute) {
4023 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
4024 is_external_implementation = true;
4027 if (a.Type == TypeManager.dllimport_type) {
4028 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4029 if ((ModFlags & extern_static) != extern_static) {
4030 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
4032 is_external_implementation = true;
4035 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4036 if (declarative_security == null)
4037 declarative_security = new ListDictionary ();
4038 a.ExtractSecurityPermissionSet (declarative_security);
4039 return;
4042 MethodBuilder.SetCustomAttribute (cb);
4045 public override AttributeTargets AttributeTargets {
4046 get {
4047 return AttributeTargets.Method;
4051 public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
4053 return new EmitContext (
4054 this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
4057 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
4059 if (anonymous_methods == null)
4060 anonymous_methods = new ArrayList ();
4061 anonymous_methods.Add (anonymous);
4064 protected bool DefineGenericMethod ()
4066 if (!DoDefineBase ())
4067 return false;
4069 #if GMCS_SOURCE
4070 if (GenericMethod != null) {
4071 string method_name = MemberName.Name;
4073 if (IsExplicitImpl) {
4074 method_name = TypeManager.CSharpName (InterfaceType) +
4075 '.' + method_name;
4078 #if MS_COMPATIBLE
4079 MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags, ReturnType, null);
4080 #else
4081 MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
4082 #endif
4084 if (!GenericMethod.Define (MethodBuilder, block))
4085 return false;
4087 #endif
4089 return true;
4092 public bool ResolveMembers ()
4094 if (!DefineGenericMethod ())
4095 return false;
4097 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
4098 iterator = Iterator.CreateIterator (this, Parent, GenericMethod, ModFlags);
4099 if (iterator == null)
4100 return false;
4103 if (anonymous_methods != null) {
4104 foreach (AnonymousMethodExpression ame in anonymous_methods) {
4105 if (!ame.CreateAnonymousHelpers ())
4106 return false;
4110 return true;
4113 public override bool Define ()
4115 if (!DoDefine ())
4116 return false;
4118 if (!CheckAbstractAndExtern (block != null))
4119 return false;
4121 if (!CheckBase ())
4122 return false;
4124 MethodData = new MethodData (
4125 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
4127 if (!MethodData.Define (Parent.PartialContainer))
4128 return false;
4130 MethodBuilder = MethodData.MethodBuilder;
4132 if (!TypeManager.IsGenericParameter (MemberType)) {
4133 if (MemberType.IsAbstract && MemberType.IsSealed) {
4134 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
4135 return false;
4139 return true;
4142 public override void Emit ()
4144 if (OptAttributes != null)
4145 OptAttributes.Emit ();
4147 if (declarative_security != null) {
4148 foreach (DictionaryEntry de in declarative_security) {
4149 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4153 base.Emit ();
4156 protected void Error_ConditionalAttributeIsNotValid ()
4158 Report.Error (577, Location,
4159 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
4160 GetSignatureForError ());
4163 public override bool MarkForDuplicationCheck ()
4165 caching_flags |= Flags.TestMethodDuplication;
4166 return true;
4169 public override string[] ValidAttributeTargets {
4170 get {
4171 return attribute_targets;
4175 #region IMethodData Members
4177 public CallingConventions CallingConventions {
4178 get {
4179 CallingConventions cc = Parameters.CallingConvention;
4180 if (Parameters.HasArglist && block != null)
4181 block.HasVarargs = true;
4183 if (!IsInterface)
4184 if ((ModFlags & Modifiers.STATIC) == 0)
4185 cc |= CallingConventions.HasThis;
4187 // FIXME: How is `ExplicitThis' used in C#?
4189 return cc;
4193 public Type ReturnType {
4194 get {
4195 return MemberType;
4199 public MemberName MethodName {
4200 get {
4201 return MemberName;
4205 public Iterator Iterator {
4206 get { return iterator; }
4209 public new Location Location {
4210 get {
4211 return base.Location;
4215 protected override bool CheckBase ()
4217 if (!base.CheckBase ())
4218 return false;
4220 // TODO: Destructor should derive from MethodCore
4221 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == "Finalize" &&
4222 base_method.DeclaringType == TypeManager.object_type && !(this is Destructor)) {
4223 Report.Error (249, Location, "Do not override object.Finalize. Instead, provide a destructor");
4224 return false;
4227 return true;
4230 /// <summary>
4231 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
4232 /// </summary>
4233 public bool IsExcluded () {
4234 if ((caching_flags & Flags.Excluded_Undetected) == 0)
4235 return (caching_flags & Flags.Excluded) != 0;
4237 caching_flags &= ~Flags.Excluded_Undetected;
4239 if (base_method == null) {
4240 if (OptAttributes == null)
4241 return false;
4243 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type);
4245 if (attrs == null)
4246 return false;
4248 foreach (Attribute a in attrs) {
4249 string condition = a.GetConditionalAttributeValue ();
4250 if (condition == null)
4251 return false;
4253 if (RootContext.AllDefines.Contains (condition))
4254 return false;
4257 caching_flags |= Flags.Excluded;
4258 return true;
4261 IMethodData md = TypeManager.GetMethod (base_method);
4262 if (md == null) {
4263 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
4264 caching_flags |= Flags.Excluded;
4265 return true;
4267 return false;
4270 if (md.IsExcluded ()) {
4271 caching_flags |= Flags.Excluded;
4272 return true;
4274 return false;
4277 GenericMethod IMethodData.GenericMethod {
4278 get {
4279 return GenericMethod;
4283 #endregion
4287 public class SourceMethod : ISourceMethod
4289 DeclSpace parent;
4290 MethodBase builder;
4292 protected SourceMethod (DeclSpace parent, MethodBase builder,
4293 ISourceFile file, Location start, Location end)
4295 this.parent = parent;
4296 this.builder = builder;
4298 CodeGen.SymbolWriter.OpenMethod (file, this, start.Row, start.Column, end.Row, start.Column);
4301 public string Name {
4302 get { return builder.Name; }
4305 public int NamespaceID {
4306 get { return parent.NamespaceEntry.SymbolFileID; }
4309 public int Token {
4310 get {
4311 if (builder is MethodBuilder)
4312 return ((MethodBuilder) builder).GetToken ().Token;
4313 else if (builder is ConstructorBuilder)
4314 return ((ConstructorBuilder) builder).GetToken ().Token;
4315 else
4316 throw new NotSupportedException ();
4320 public void CloseMethod ()
4322 if (CodeGen.SymbolWriter != null)
4323 CodeGen.SymbolWriter.CloseMethod ();
4326 public static SourceMethod Create (DeclSpace parent, MethodBase builder, Block block)
4328 if (CodeGen.SymbolWriter == null)
4329 return null;
4330 if (block == null)
4331 return null;
4333 Location start_loc = block.StartLocation;
4334 if (start_loc.IsNull)
4335 return null;
4337 Location end_loc = block.EndLocation;
4338 if (end_loc.IsNull)
4339 return null;
4341 ISourceFile file = start_loc.SourceFile;
4342 if (file == null)
4343 return null;
4345 return new SourceMethod (
4346 parent, builder, file, start_loc, end_loc);
4350 public class Method : MethodOrOperator, IAnonymousHost {
4352 /// <summary>
4353 /// Modifiers allowed in a class declaration
4354 /// </summary>
4355 const int AllowedModifiers =
4356 Modifiers.NEW |
4357 Modifiers.PUBLIC |
4358 Modifiers.PROTECTED |
4359 Modifiers.INTERNAL |
4360 Modifiers.PRIVATE |
4361 Modifiers.STATIC |
4362 Modifiers.VIRTUAL |
4363 Modifiers.SEALED |
4364 Modifiers.OVERRIDE |
4365 Modifiers.ABSTRACT |
4366 Modifiers.UNSAFE |
4367 Modifiers.METHOD_YIELDS |
4368 Modifiers.EXTERN;
4370 const int AllowedInterfaceModifiers =
4371 Modifiers.NEW | Modifiers.UNSAFE;
4374 // return_type can be "null" for VOID values.
4376 public Method (DeclSpace parent, GenericMethod generic,
4377 Expression return_type, int mod, bool is_iface,
4378 MemberName name, Parameters parameters, Attributes attrs)
4379 : base (parent, generic, return_type, mod,
4380 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
4381 is_iface, name, attrs, parameters)
4385 public override string GetSignatureForError()
4387 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4390 void Error_DuplicateEntryPoint (MethodInfo b, Location location)
4392 Report.Error (17, location,
4393 "Program `{0}' has more than one entry point defined: `{1}'",
4394 CodeGen.FileName, TypeManager.CSharpSignature(b));
4397 bool IsEntryPoint ()
4399 if (ReturnType != TypeManager.void_type &&
4400 ReturnType != TypeManager.int32_type)
4401 return false;
4403 if (Parameters.Count == 0)
4404 return true;
4406 if (Parameters.Count > 1)
4407 return false;
4409 Type t = Parameters.ParameterType (0);
4410 return t.IsArray && t.GetArrayRank () == 1 &&
4411 TypeManager.GetElementType (t) == TypeManager.string_type &&
4412 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
4415 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4417 if (a.Type == TypeManager.conditional_attribute_type) {
4418 if (IsExplicitImpl) {
4419 Error_ConditionalAttributeIsNotValid ();
4420 return;
4423 if (ReturnType != TypeManager.void_type) {
4424 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4425 return;
4428 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4429 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4430 return;
4433 if (IsInterface) {
4434 Report.Error (582, Location, "Conditional not valid on interface members");
4435 return;
4438 if (MethodData.implementing != null) {
4439 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4440 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4441 return;
4444 for (int i = 0; i < Parameters.Count; ++i) {
4445 if ((Parameters.ParameterModifier (i) & Parameter.Modifier.OUTMASK) != 0) {
4446 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4447 return;
4452 if (a.Type == TypeManager.extension_attribute_type) {
4453 a.Error_MisusedExtensionAttribute ();
4454 return;
4457 base.ApplyAttributeBuilder (a, cb);
4460 protected override bool CheckForDuplications ()
4462 ArrayList ar = Parent.PartialContainer.Methods;
4463 if (ar != null) {
4464 int arLen = ar.Count;
4466 for (int i = 0; i < arLen; i++) {
4467 Method m = (Method) ar [i];
4468 if (IsDuplicateImplementation (m))
4469 return false;
4473 ar = Parent.PartialContainer.Properties;
4474 if (ar != null) {
4475 for (int i = 0; i < ar.Count; ++i) {
4476 PropertyBase pb = (PropertyBase) ar [i];
4477 if (pb.AreAccessorsDuplicateImplementation (this))
4478 return false;
4482 ar = Parent.PartialContainer.Indexers;
4483 if (ar != null) {
4484 for (int i = 0; i < ar.Count; ++i) {
4485 PropertyBase pb = (PropertyBase) ar [i];
4486 if (pb.AreAccessorsDuplicateImplementation (this))
4487 return false;
4491 ar = Parent.PartialContainer.Events;
4492 if (ar != null) {
4493 for (int i = 0; i < ar.Count; ++i) {
4494 Event ev = (Event) ar [i];
4495 if (ev.AreAccessorsDuplicateImplementation (this))
4496 return false;
4500 return true;
4504 // Creates the type
4506 public override bool Define ()
4508 if (!base.Define ())
4509 return false;
4511 if (RootContext.StdLib && (ReturnType == TypeManager.arg_iterator_type || ReturnType == TypeManager.typed_reference_type)) {
4512 Error1599 (Location, ReturnType);
4513 return false;
4516 if (ReturnType == TypeManager.void_type && ParameterTypes.Length == 0 &&
4517 Name == "Finalize" && !(this is Destructor)) {
4518 Report.Warning (465, 1, Location, "Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4521 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
4522 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
4523 Parent.PartialContainer.Mark_HasEquals ();
4524 else if (Parameters.Empty && Name == "GetHashCode")
4525 Parent.PartialContainer.Mark_HasGetHashCode ();
4528 if ((ModFlags & Modifiers.STATIC) == 0)
4529 return true;
4531 if (Parameters.HasExtensionMethodType) {
4532 if (Parent.IsStaticClass && !Parent.IsGeneric) {
4533 if (!Parent.IsTopLevel)
4534 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
4535 GetSignatureForError ());
4537 if (TypeManager.extension_attribute_type == null)
4538 Report.Error (1110, Location,
4539 "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
4540 GetSignatureForError ());
4542 ModFlags |= Modifiers.METHOD_EXTENSION;
4543 Parent.ModFlags |= Modifiers.METHOD_EXTENSION;
4544 CodeGen.Assembly.HasExtensionMethods = true;
4545 } else {
4546 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
4547 GetSignatureForError ());
4552 // This is used to track the Entry Point,
4554 if (RootContext.NeedsEntryPoint &&
4555 Name == "Main" &&
4556 (RootContext.MainClass == null ||
4557 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4558 if (IsEntryPoint ()) {
4560 if (RootContext.EntryPoint == null) {
4561 if (Parent.IsGeneric || MemberName.IsGeneric) {
4562 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
4563 GetSignatureForError ());
4564 } else {
4565 IMethodData md = TypeManager.GetMethod (MethodBuilder);
4566 md.SetMemberIsUsed ();
4568 RootContext.EntryPoint = MethodBuilder;
4569 RootContext.EntryPointLocation = Location;
4571 } else {
4572 Error_DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
4573 Error_DuplicateEntryPoint (MethodBuilder, Location);
4575 } else {
4576 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
4577 GetSignatureForError ());
4581 return true;
4585 // Emits the code
4587 public override void Emit ()
4589 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
4590 MethodData.Emit (Parent);
4591 base.Emit ();
4593 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
4594 MethodBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
4596 Block = null;
4597 MethodData = null;
4600 public static void Error1599 (Location loc, Type t)
4602 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4605 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4607 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
4608 Parent.TypeBuilder, Name, ParameterTypes, GenericMethod, false);
4610 if (mi == null)
4611 return null;
4613 if (mi.IsSpecialName)
4614 return null;
4616 base_ret_type = mi.ReturnType;
4617 return mi;
4620 protected override bool VerifyClsCompliance ()
4622 if (!base.VerifyClsCompliance ())
4623 return false;
4625 if (ParameterInfo.Count > 0) {
4626 ArrayList al = (ArrayList)Parent.PartialContainer.MemberCache.Members [Name];
4627 if (al.Count > 1)
4628 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4631 return true;
4635 public abstract class ConstructorInitializer {
4636 ArrayList argument_list;
4637 protected ConstructorInfo base_constructor;
4638 Location loc;
4640 public ConstructorInitializer (ArrayList argument_list, Location loc)
4642 this.argument_list = argument_list;
4643 this.loc = loc;
4646 public ArrayList Arguments {
4647 get {
4648 return argument_list;
4652 public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
4654 Expression base_constructor_group;
4655 Type t;
4656 bool error = false;
4658 ec.CurrentBlock = block;
4660 if (argument_list != null){
4661 foreach (Argument a in argument_list){
4662 if (!a.Resolve (ec, loc))
4663 return false;
4666 ec.CurrentBlock = null;
4668 if (this is ConstructorBaseInitializer) {
4669 if (ec.ContainerType.BaseType == null)
4670 return true;
4672 t = ec.ContainerType.BaseType;
4673 if (ec.ContainerType.IsValueType) {
4674 Report.Error (522, loc,
4675 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4676 return false;
4678 } else {
4680 // It is legal to have "this" initializers that take no arguments
4681 // in structs, they are just no-ops.
4683 // struct D { public D (int a) : this () {}
4685 if (ec.ContainerType.IsValueType && argument_list == null)
4686 return true;
4688 t = ec.ContainerType;
4691 base_constructor_group = Expression.MemberLookup (
4692 ec.ContainerType, t, ".ctor", MemberTypes.Constructor,
4693 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4694 loc);
4696 if (base_constructor_group == null){
4697 error = true;
4698 base_constructor_group = Expression.MemberLookup (
4699 t, null, t, ".ctor", MemberTypes.Constructor,
4700 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4701 loc);
4704 int errors = Report.Errors;
4705 if (base_constructor_group != null)
4706 base_constructor = (ConstructorInfo)
4707 ((MethodGroupExpr) base_constructor_group).OverloadResolve (
4708 ec, argument_list,
4709 false, loc);
4711 if (base_constructor == null) {
4712 if (errors == Report.Errors)
4713 Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
4714 argument_list == null ? 0 : argument_list.Count);
4715 return false;
4718 if (error) {
4719 Report.SymbolRelatedToPreviousError (base_constructor);
4720 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
4721 base_constructor = null;
4722 return false;
4725 if (base_constructor == caller_builder){
4726 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4727 return false;
4730 return true;
4733 public virtual void Emit (EmitContext ec)
4735 if (base_constructor != null){
4736 ec.Mark (loc, false);
4737 if (ec.IsStatic)
4738 Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4739 else
4740 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4745 public class ConstructorBaseInitializer : ConstructorInitializer {
4746 public ConstructorBaseInitializer (ArrayList argument_list, Location l) :
4747 base (argument_list, l)
4752 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4753 public GeneratedBaseInitializer (Location loc):
4754 base (null, loc)
4759 public class ConstructorThisInitializer : ConstructorInitializer {
4760 public ConstructorThisInitializer (ArrayList argument_list, Location l) :
4761 base (argument_list, l)
4766 public class Constructor : MethodCore, IMethodData, IAnonymousHost {
4767 public ConstructorBuilder ConstructorBuilder;
4768 public ConstructorInitializer Initializer;
4769 ListDictionary declarative_security;
4770 ArrayList anonymous_methods;
4772 // <summary>
4773 // Modifiers allowed for a constructor.
4774 // </summary>
4775 public const int AllowedModifiers =
4776 Modifiers.PUBLIC |
4777 Modifiers.PROTECTED |
4778 Modifiers.INTERNAL |
4779 Modifiers.STATIC |
4780 Modifiers.UNSAFE |
4781 Modifiers.EXTERN |
4782 Modifiers.PRIVATE;
4784 static string[] attribute_targets = new string [] { "method" };
4786 public Iterator Iterator {
4787 get { return null; }
4790 bool has_compliant_args = false;
4792 // The spec claims that static is not permitted, but
4793 // my very own code has static constructors.
4795 public Constructor (DeclSpace parent, string name, int mod, Parameters args,
4796 ConstructorInitializer init, Location loc)
4797 : base (parent, null, null, mod, AllowedModifiers, false,
4798 new MemberName (name, loc), null, args)
4800 Initializer = init;
4803 public bool HasCompliantArgs {
4804 get { return has_compliant_args; }
4807 public override AttributeTargets AttributeTargets {
4808 get { return AttributeTargets.Constructor; }
4813 // Returns true if this is a default constructor
4815 public bool IsDefault ()
4817 if ((ModFlags & Modifiers.STATIC) != 0)
4818 return Parameters.Empty;
4820 return Parameters.Empty &&
4821 (Initializer is ConstructorBaseInitializer) &&
4822 (Initializer.Arguments == null);
4825 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4827 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4828 if (declarative_security == null) {
4829 declarative_security = new ListDictionary ();
4831 a.ExtractSecurityPermissionSet (declarative_security);
4832 return;
4835 if (a.IsInternalMethodImplAttribute) {
4836 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
4837 is_external_implementation = true;
4840 ConstructorBuilder.SetCustomAttribute (cb);
4843 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
4845 if (anonymous_methods == null)
4846 anonymous_methods = new ArrayList ();
4847 anonymous_methods.Add (anonymous);
4850 public bool ResolveMembers ()
4852 if (anonymous_methods != null) {
4853 foreach (AnonymousMethodExpression ame in anonymous_methods) {
4854 if (!ame.CreateAnonymousHelpers ())
4855 return false;
4859 return true;
4862 protected override bool CheckForDuplications ()
4864 ArrayList ar = Parent.PartialContainer.InstanceConstructors;
4865 if (ar != null) {
4866 int arLen = ar.Count;
4868 for (int i = 0; i < arLen; i++) {
4869 Constructor m = (Constructor) ar [i];
4870 if (IsDuplicateImplementation (m))
4871 return false;
4874 return true;
4877 protected override bool CheckBase ()
4879 if ((ModFlags & Modifiers.STATIC) != 0) {
4880 if (!Parameters.Empty) {
4881 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
4882 GetSignatureForError ());
4883 return false;
4886 // the rest can be ignored
4887 return true;
4890 // Check whether arguments were correct.
4891 if (!DefineParameters (Parameters))
4892 return false;
4894 if (!CheckForDuplications ())
4895 return false;
4897 if (Parent.PartialContainer.Kind == Kind.Struct) {
4898 if (ParameterTypes.Length == 0) {
4899 Report.Error (568, Location,
4900 "Structs cannot contain explicit parameterless constructors");
4901 return false;
4904 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4905 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4906 return false;
4910 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4911 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4914 return true;
4918 // Creates the ConstructorBuilder
4920 public override bool Define ()
4922 if (ConstructorBuilder != null)
4923 return true;
4925 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4926 MethodAttributes.SpecialName);
4928 if ((ModFlags & Modifiers.STATIC) != 0) {
4929 ca |= MethodAttributes.Static | MethodAttributes.Private;
4930 } else {
4931 ca |= MethodAttributes.HideBySig;
4933 if ((ModFlags & Modifiers.PUBLIC) != 0)
4934 ca |= MethodAttributes.Public;
4935 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4936 if ((ModFlags & Modifiers.INTERNAL) != 0)
4937 ca |= MethodAttributes.FamORAssem;
4938 else
4939 ca |= MethodAttributes.Family;
4940 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4941 ca |= MethodAttributes.Assembly;
4942 else
4943 ca |= MethodAttributes.Private;
4946 if (!CheckAbstractAndExtern (block != null))
4947 return false;
4949 // Check if arguments were correct.
4950 if (!CheckBase ())
4951 return false;
4953 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4954 ca, CallingConventions,
4955 ParameterTypes);
4957 if ((ModFlags & Modifiers.UNSAFE) != 0)
4958 ConstructorBuilder.InitLocals = false;
4960 if (Parent.PartialContainer.IsComImport) {
4961 if (!IsDefault ()) {
4962 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
4963 Parent.GetSignatureForError ());
4964 return false;
4966 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
4969 TypeManager.AddMethod (ConstructorBuilder, this);
4971 return true;
4975 // Emits the code
4977 public override void Emit ()
4979 if (OptAttributes != null)
4980 OptAttributes.Emit ();
4982 EmitContext ec = CreateEmitContext (null, null);
4984 if (block != null) {
4985 // If this is a non-static `struct' constructor and doesn't have any
4986 // initializer, it must initialize all of the struct's fields.
4987 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
4988 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4989 block.AddThisVariable (Parent, Location);
4991 if (!block.ResolveMeta (ec, ParameterInfo))
4992 block = null;
4995 if ((ModFlags & Modifiers.STATIC) == 0){
4996 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
4997 Initializer = new GeneratedBaseInitializer (Location);
5001 // Spec mandates that Initializers will not have
5002 // `this' access
5004 ec.IsStatic = true;
5005 if ((Initializer != null) &&
5006 !Initializer.Resolve (ConstructorBuilder, block, ec))
5007 return;
5008 ec.IsStatic = false;
5011 Parameters.ApplyAttributes (ConstructorBuilder);
5013 SourceMethod source = SourceMethod.Create (
5014 Parent, ConstructorBuilder, block);
5017 // Classes can have base initializers and instance field initializers.
5019 if (Parent.PartialContainer.Kind == Kind.Class){
5020 if ((ModFlags & Modifiers.STATIC) == 0){
5023 // If we use a "this (...)" constructor initializer, then
5024 // do not emit field initializers, they are initialized in the other constructor
5026 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
5027 Parent.PartialContainer.EmitFieldInitializers (ec);
5031 bool unreachable = false;
5032 if (block != null) {
5033 if (!ec.ResolveTopBlock (null, block, ParameterInfo, this, out unreachable))
5034 return;
5035 ec.EmitMeta (block);
5037 if (block.ScopeInfo != null) {
5038 ExpressionStatement init = block.ScopeInfo.GetScopeInitializer (ec);
5039 init.EmitStatement (ec);
5043 if (Initializer != null) {
5044 Initializer.Emit (ec);
5047 if ((ModFlags & Modifiers.STATIC) != 0)
5048 Parent.PartialContainer.EmitFieldInitializers (ec);
5050 if (block != null)
5051 ec.EmitResolvedTopBlock (block, unreachable);
5053 if (source != null)
5054 source.CloseMethod ();
5056 base.Emit ();
5058 if (declarative_security != null) {
5059 foreach (DictionaryEntry de in declarative_security) {
5060 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
5064 block = null;
5067 // Is never override
5068 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5070 return null;
5073 public override string GetSignatureForError()
5075 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
5078 public override string[] ValidAttributeTargets {
5079 get {
5080 return attribute_targets;
5084 protected override bool VerifyClsCompliance ()
5086 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
5087 return false;
5090 if (ParameterInfo.Count > 0) {
5091 ArrayList al = (ArrayList)Parent.MemberCache.Members [".ctor"];
5092 if (al.Count > 3)
5093 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
5095 if (Parent.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
5096 foreach (Type param in ParameterTypes) {
5097 if (param.IsArray) {
5098 return true;
5103 has_compliant_args = true;
5104 return true;
5107 #region IMethodData Members
5109 public System.Reflection.CallingConventions CallingConventions {
5110 get {
5111 CallingConventions cc = Parameters.CallingConvention;
5113 if (Parent.PartialContainer.Kind == Kind.Class)
5114 if ((ModFlags & Modifiers.STATIC) == 0)
5115 cc |= CallingConventions.HasThis;
5117 // FIXME: How is `ExplicitThis' used in C#?
5119 return cc;
5123 public new Location Location {
5124 get {
5125 return base.Location;
5129 public MemberName MethodName {
5130 get {
5131 return MemberName;
5135 public Type ReturnType {
5136 get {
5137 return MemberType;
5141 public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
5143 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
5144 return new EmitContext (this, Parent, Location, ig_, null, ModFlags, true);
5147 public bool IsExcluded()
5149 return false;
5152 GenericMethod IMethodData.GenericMethod {
5153 get {
5154 return null;
5158 #endregion
5161 /// <summary>
5162 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
5163 /// </summary>
5164 public interface IMethodData
5166 CallingConventions CallingConventions { get; }
5167 Location Location { get; }
5168 MemberName MethodName { get; }
5169 Type ReturnType { get; }
5170 GenericMethod GenericMethod { get; }
5171 Parameters ParameterInfo { get; }
5173 Iterator Iterator { get; }
5175 Attributes OptAttributes { get; }
5176 ToplevelBlock Block { get; set; }
5178 EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
5179 ObsoleteAttribute GetObsoleteAttribute ();
5180 string GetSignatureForError ();
5181 bool IsExcluded ();
5182 bool IsClsComplianceRequired ();
5183 void SetMemberIsUsed ();
5187 // Encapsulates most of the Method's state
5189 public class MethodData {
5191 readonly IMethodData method;
5193 public readonly GenericMethod GenericMethod;
5196 // Are we implementing an interface ?
5198 public MethodInfo implementing;
5201 // Protected data.
5203 protected InterfaceMemberBase member;
5204 protected int modifiers;
5205 protected MethodAttributes flags;
5206 protected Type declaring_type;
5207 protected MethodInfo parent_method;
5209 MethodBuilder builder = null;
5210 public MethodBuilder MethodBuilder {
5211 get {
5212 return builder;
5216 public Type DeclaringType {
5217 get {
5218 return declaring_type;
5222 public MethodData (InterfaceMemberBase member,
5223 int modifiers, MethodAttributes flags, IMethodData method)
5225 this.member = member;
5226 this.modifiers = modifiers;
5227 this.flags = flags;
5229 this.method = method;
5232 public MethodData (InterfaceMemberBase member,
5233 int modifiers, MethodAttributes flags,
5234 IMethodData method, MethodBuilder builder,
5235 GenericMethod generic, MethodInfo parent_method)
5236 : this (member, modifiers, flags, method)
5238 this.builder = builder;
5239 this.GenericMethod = generic;
5240 this.parent_method = parent_method;
5243 public bool Define (DeclSpace parent)
5245 string name = method.MethodName.Basename;
5246 string method_name = method.MethodName.FullName;
5248 TypeContainer container = parent.PartialContainer;
5250 PendingImplementation pending = container.PendingImplementations;
5251 if (pending != null){
5252 if (member is Indexer) // TODO: test it, but it should work without this IF
5253 implementing = pending.IsInterfaceIndexer (
5254 member.InterfaceType, method.ReturnType, method.ParameterInfo);
5255 else
5256 implementing = pending.IsInterfaceMethod (
5257 member.InterfaceType, name, method.ReturnType, method.ParameterInfo);
5259 if (member.InterfaceType != null){
5260 if (implementing == null){
5261 if (member is PropertyBase) {
5262 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
5263 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
5264 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
5266 } else {
5267 Report.Error (539, method.Location,
5268 "`{0}.{1}' in explicit interface declaration is not a member of interface",
5269 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
5271 return false;
5273 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
5274 Report.SymbolRelatedToPreviousError (implementing);
5275 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
5276 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
5277 return false;
5280 method_name = member.InterfaceType.FullName +
5281 '.' + method_name;
5282 } else {
5283 if (implementing != null) {
5284 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
5285 if (prop_method == null) {
5286 if (implementing.IsSpecialName) {
5287 Report.SymbolRelatedToPreviousError (implementing);
5288 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
5289 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
5290 implementing.Name.StartsWith ("get_") ? "get" : "set");
5291 return false;
5293 } else if (implementing.DeclaringType.IsInterface) {
5294 if (!implementing.IsSpecialName) {
5295 Report.SymbolRelatedToPreviousError (implementing);
5296 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
5297 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
5298 return false;
5300 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
5301 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
5302 Report.SymbolRelatedToPreviousError (implementing);
5303 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
5304 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
5305 return false;
5313 // For implicit implementations, make sure we are public, for
5314 // explicit implementations, make sure we are private.
5316 if (implementing != null){
5318 // Setting null inside this block will trigger a more
5319 // verbose error reporting for missing interface implementations
5321 // The "candidate" function has been flagged already
5322 // but it wont get cleared
5324 if (member.IsExplicitImpl){
5325 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
5326 Report.SymbolRelatedToPreviousError (implementing);
5327 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
5328 method.GetSignatureForError ());
5329 return false;
5331 } else {
5332 if (implementing.DeclaringType.IsInterface) {
5334 // If this is an interface method implementation,
5335 // check for public accessibility
5337 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
5339 implementing = null;
5341 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5342 // We may never be private.
5343 implementing = null;
5345 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5347 // We may be protected if we're overriding something.
5349 implementing = null;
5354 // Static is not allowed
5356 if ((modifiers & Modifiers.STATIC) != 0){
5357 implementing = null;
5362 // If implementing is still valid, set flags
5364 if (implementing != null){
5366 // When implementing interface methods, set NewSlot
5367 // unless, we are overwriting a method.
5369 if (implementing.DeclaringType.IsInterface){
5370 if ((modifiers & Modifiers.OVERRIDE) == 0)
5371 flags |= MethodAttributes.NewSlot;
5373 flags |=
5374 MethodAttributes.Virtual |
5375 MethodAttributes.HideBySig;
5377 // Set Final unless we're virtual, abstract or already overriding a method.
5378 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5379 flags |= MethodAttributes.Final;
5382 EmitContext ec = method.CreateEmitContext (container, null);
5384 DefineMethodBuilder (container, method_name, method.ParameterInfo.Types);
5386 if (builder == null)
5387 return false;
5389 if (container.CurrentType != null)
5390 declaring_type = container.CurrentType;
5391 else
5392 declaring_type = container.TypeBuilder;
5394 if ((modifiers & Modifiers.UNSAFE) != 0)
5395 builder.InitLocals = false;
5398 if (implementing != null){
5400 // clear the pending implemntation flag
5402 if (member is Indexer) {
5403 pending.ImplementIndexer (
5404 member.InterfaceType, builder, method.ReturnType,
5405 method.ParameterInfo, member.IsExplicitImpl);
5406 } else
5407 pending.ImplementMethod (
5408 member.InterfaceType, name, method.ReturnType,
5409 method.ParameterInfo, member.IsExplicitImpl);
5411 if (member.IsExplicitImpl)
5412 container.TypeBuilder.DefineMethodOverride (
5413 builder, implementing);
5416 TypeManager.AddMethod (builder, method);
5418 if (GenericMethod != null) {
5419 bool is_override = member.IsExplicitImpl |
5420 ((modifiers & Modifiers.OVERRIDE) != 0);
5422 if (implementing != null)
5423 parent_method = implementing;
5425 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5426 return false;
5429 return true;
5433 /// <summary>
5434 /// Create the MethodBuilder for the method
5435 /// </summary>
5436 void DefineMethodBuilder (TypeContainer container, string method_name, Type[] ParameterTypes)
5438 if (builder == null) {
5439 builder = container.TypeBuilder.DefineMethod (
5440 method_name, flags, method.CallingConventions,
5441 method.ReturnType, ParameterTypes);
5442 return;
5445 #if GMCS_SOURCE && !MS_COMPATIBLE
5446 builder.SetGenericMethodSignature (
5447 flags, method.CallingConventions,
5448 method.ReturnType, ParameterTypes);
5449 #endif
5453 // Emits the code
5455 public void Emit (DeclSpace parent)
5457 ToplevelBlock block = method.Block;
5459 EmitContext ec;
5460 if (block != null)
5461 ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
5462 else
5463 ec = method.CreateEmitContext (parent, null);
5465 method.ParameterInfo.ApplyAttributes (MethodBuilder);
5467 if (GenericMethod != null)
5468 GenericMethod.EmitAttributes ();
5470 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
5473 // Handle destructors specially
5475 // FIXME: This code generates buggy code
5477 if (member is Destructor)
5478 EmitDestructor (ec, block);
5479 else
5480 ec.EmitTopBlock (method, block);
5482 if (source != null)
5483 source.CloseMethod ();
5486 void EmitDestructor (EmitContext ec, ToplevelBlock block)
5488 ILGenerator ig = ec.ig;
5490 Label finish = ig.DefineLabel ();
5492 block.SetDestructor ();
5494 ig.BeginExceptionBlock ();
5495 ec.ReturnLabel = finish;
5496 ec.HasReturnLabel = true;
5497 ec.EmitTopBlock (method, block);
5499 // ig.MarkLabel (finish);
5500 ig.BeginFinallyBlock ();
5502 if (ec.ContainerType.BaseType != null) {
5503 Expression member_lookup = Expression.MemberLookup (
5504 ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
5505 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
5507 if (member_lookup != null){
5508 MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
5510 ig.Emit (OpCodes.Ldarg_0);
5511 ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
5515 ig.EndExceptionBlock ();
5516 //ig.MarkLabel (ec.ReturnLabel);
5517 ig.Emit (OpCodes.Ret);
5521 // TODO: Should derive from MethodCore
5522 public class Destructor : Method {
5524 static string[] attribute_targets = new string [] { "method" };
5526 public Destructor (DeclSpace parent, Expression return_type, int mod,
5527 string name, Parameters parameters, Attributes attrs,
5528 Location l)
5529 : base (parent, null, return_type, mod, false, new MemberName (name, l),
5530 parameters, attrs)
5533 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5535 if (a.Type == TypeManager.conditional_attribute_type) {
5536 Error_ConditionalAttributeIsNotValid ();
5537 return;
5540 base.ApplyAttributeBuilder (a, cb);
5543 public override string GetSignatureForError ()
5545 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5548 public override string[] ValidAttributeTargets {
5549 get {
5550 return attribute_targets;
5555 abstract public class MemberBase : MemberCore {
5556 public Expression Type;
5557 public readonly DeclSpace ds;
5558 public readonly GenericMethod GenericMethod;
5561 // The type of this property / indexer / event
5563 protected Type member_type;
5564 public Type MemberType {
5565 get {
5566 if (member_type == null && Type != null) {
5567 IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
5568 Type = Type.ResolveAsTypeTerminal (rc, false);
5569 if (Type != null) {
5570 member_type = Type.Type;
5573 return member_type;
5578 // The constructor is only exposed to our children
5580 protected MemberBase (DeclSpace parent, GenericMethod generic,
5581 Expression type, int mod, int allowed_mod, int def_mod,
5582 MemberName name, Attributes attrs)
5583 : base (parent, name, attrs)
5585 this.ds = generic != null ? generic : (DeclSpace) parent;
5586 Type = type;
5587 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
5588 GenericMethod = generic;
5589 if (GenericMethod != null)
5590 GenericMethod.ModFlags = ModFlags;
5593 protected virtual bool CheckBase ()
5595 if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.PartialContainer.Kind == Kind.Struct) {
5596 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
5597 return false;
5600 if ((RootContext.WarningLevel >= 4) &&
5601 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
5602 ((ModFlags & Modifiers.PROTECTED) != 0) &&
5603 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
5604 Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
5606 return true;
5609 protected virtual bool DoDefine ()
5611 if (MemberType == null)
5612 return false;
5614 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5615 (ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0) {
5616 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5617 GetSignatureForError (), Parent.GetSignatureForError ());
5618 return false;
5621 // verify accessibility
5622 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5623 Report.SymbolRelatedToPreviousError (MemberType);
5624 if (this is Property)
5625 Report.Error (53, Location,
5626 "Inconsistent accessibility: property type `" +
5627 TypeManager.CSharpName (MemberType) + "' is less " +
5628 "accessible than property `" + GetSignatureForError () + "'");
5629 else if (this is Indexer)
5630 Report.Error (54, Location,
5631 "Inconsistent accessibility: indexer return type `" +
5632 TypeManager.CSharpName (MemberType) + "' is less " +
5633 "accessible than indexer `" + GetSignatureForError () + "'");
5634 else if (this is MethodCore) {
5635 if (this is Operator)
5636 Report.Error (56, Location,
5637 "Inconsistent accessibility: return type `" +
5638 TypeManager.CSharpName (MemberType) + "' is less " +
5639 "accessible than operator `" + GetSignatureForError () + "'");
5640 else
5641 Report.Error (50, Location,
5642 "Inconsistent accessibility: return type `" +
5643 TypeManager.CSharpName (MemberType) + "' is less " +
5644 "accessible than method `" + GetSignatureForError () + "'");
5645 } else {
5646 Report.Error (52, Location,
5647 "Inconsistent accessibility: field type `" +
5648 TypeManager.CSharpName (MemberType) + "' is less " +
5649 "accessible than field `" + GetSignatureForError () + "'");
5651 return false;
5654 return true;
5657 protected bool IsTypePermitted ()
5659 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5660 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5661 return false;
5663 return true;
5668 // Abstract class for all fields
5670 abstract public class FieldBase : MemberBase {
5671 public FieldBuilder FieldBuilder;
5672 public Status status;
5673 protected Expression initializer;
5675 [Flags]
5676 public enum Status : byte {
5677 HAS_OFFSET = 4 // Used by FieldMember.
5680 static readonly string[] attribute_targets = new string [] { "field" };
5682 protected FieldBase (DeclSpace parent, Expression type, int mod,
5683 int allowed_mod, MemberName name, Attributes attrs)
5684 : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE,
5685 name, attrs)
5687 if ((mod & Modifiers.ABSTRACT) != 0)
5688 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5691 public override AttributeTargets AttributeTargets {
5692 get {
5693 return AttributeTargets.Field;
5697 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5699 if (a.Type == TypeManager.field_offset_attribute_type) {
5700 status |= Status.HAS_OFFSET;
5702 if (!Parent.PartialContainer.HasExplicitLayout) {
5703 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5704 return;
5707 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5708 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5709 return;
5713 #if NET_2_0
5714 if (a.Type == TypeManager.fixed_buffer_attr_type) {
5715 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5716 return;
5718 #endif
5720 if (a.Type == TypeManager.marshal_as_attr_type) {
5721 UnmanagedMarshal marshal = a.GetMarshal (this);
5722 if (marshal != null) {
5723 FieldBuilder.SetMarshal (marshal);
5725 return;
5728 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5729 a.Error_InvalidSecurityParent ();
5730 return;
5733 FieldBuilder.SetCustomAttribute (cb);
5736 protected override bool CheckBase ()
5738 if (!base.CheckBase ())
5739 return false;
5741 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, false);
5742 if (conflict_symbol == null) {
5743 if ((ModFlags & Modifiers.NEW) != 0) {
5744 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5746 return true;
5749 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5750 Report.SymbolRelatedToPreviousError (conflict_symbol);
5751 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5752 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5755 return true;
5758 public override bool Define()
5760 if (MemberType == null || Type == null)
5761 return false;
5763 if (TypeManager.IsGenericParameter (MemberType))
5764 return true;
5766 if (MemberType == TypeManager.void_type) {
5767 // TODO: wrong location
5768 Expression.Error_VoidInvalidInTheContext (Location);
5769 return false;
5772 if (MemberType.IsSealed && MemberType.IsAbstract) {
5773 Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType);
5774 return false;
5777 if (!CheckBase ())
5778 return false;
5780 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5781 Report.Error (52, Location,
5782 "Inconsistent accessibility: field type `" +
5783 TypeManager.CSharpName (MemberType) + "' is less " +
5784 "accessible than field `" + GetSignatureForError () + "'");
5785 return false;
5788 if (!IsTypePermitted ())
5789 return false;
5791 return true;
5795 // Represents header string for documentation comment.
5797 public override string DocCommentHeader {
5798 get { return "F:"; }
5801 public override void Emit ()
5803 if (OptAttributes != null) {
5804 OptAttributes.Emit ();
5807 if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0 && Parent.PartialContainer.HasExplicitLayout) {
5808 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5811 base.Emit ();
5814 public static void Error_VariableOfStaticClass (Location loc, string variableName, Type staticClass)
5816 Report.SymbolRelatedToPreviousError (staticClass);
5817 Report.Error (723, loc, "`{0}': cannot declare variables of static types",
5818 variableName);
5821 public Expression Initializer {
5822 set {
5823 if (value != null) {
5824 this.initializer = value;
5829 protected virtual bool IsFieldClsCompliant {
5830 get {
5831 if (FieldBuilder == null)
5832 return true;
5834 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5838 public override string[] ValidAttributeTargets
5840 get {
5841 return attribute_targets;
5845 protected override bool VerifyClsCompliance ()
5847 if (!base.VerifyClsCompliance ())
5848 return false;
5850 if (!IsFieldClsCompliant) {
5851 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant", GetSignatureForError ());
5853 return true;
5856 public void SetAssigned ()
5858 caching_flags |= Flags.IsAssigned;
5862 interface IFixedBuffer
5864 FieldInfo Element { get; }
5865 Type ElementType { get; }
5868 public class FixedFieldExternal: IFixedBuffer
5870 FieldInfo element_field;
5872 public FixedFieldExternal (FieldInfo fi)
5874 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5877 #region IFixedField Members
5879 public FieldInfo Element {
5880 get {
5881 return element_field;
5885 public Type ElementType {
5886 get {
5887 return element_field.FieldType;
5891 #endregion
5894 /// <summary>
5895 /// Fixed buffer implementation
5896 /// </summary>
5897 public class FixedField : FieldBase, IFixedBuffer
5899 public const string FixedElementName = "FixedElementField";
5900 static int GlobalCounter = 0;
5901 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5902 static FieldInfo[] fi;
5904 TypeBuilder fixed_buffer_type;
5905 FieldBuilder element;
5906 Expression size_expr;
5907 int buffer_size;
5909 const int AllowedModifiers =
5910 Modifiers.NEW |
5911 Modifiers.PUBLIC |
5912 Modifiers.PROTECTED |
5913 Modifiers.INTERNAL |
5914 Modifiers.PRIVATE;
5916 public FixedField (DeclSpace parent, Expression type, int mod, string name,
5917 Expression size_expr, Attributes attrs, Location loc):
5918 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
5920 if (RootContext.Version == LanguageVersion.ISO_1)
5921 Report.FeatureIsNotISO1 (loc, "fixed size buffers");
5923 this.size_expr = size_expr;
5926 public override bool Define()
5928 #if !NET_2_0
5929 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
5930 Report.Warning (-23, 1, Location, "Only private or internal fixed sized buffers are supported by .NET 1.x");
5931 #endif
5933 if (Parent.PartialContainer.Kind != Kind.Struct) {
5934 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5935 GetSignatureForError ());
5936 return false;
5939 if (!base.Define ())
5940 return false;
5942 if (!TypeManager.IsPrimitiveType (MemberType)) {
5943 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",
5944 GetSignatureForError ());
5945 return false;
5948 EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
5949 Constant c = size_expr.ResolveAsConstant (ec, this);
5950 if (c == null)
5951 return false;
5953 IntConstant buffer_size_const = c.ImplicitConversionRequired (TypeManager.int32_type, Location) as IntConstant;
5954 if (buffer_size_const == null)
5955 return false;
5957 buffer_size = buffer_size_const.Value;
5959 if (buffer_size <= 0) {
5960 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5961 return false;
5964 int type_size = Expression.GetTypeSize (MemberType);
5966 if (buffer_size > int.MaxValue / type_size) {
5967 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5968 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5969 return false;
5972 buffer_size *= type_size;
5974 // Define nested
5975 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5977 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5978 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5979 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5980 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5982 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5983 TypeManager.RegisterFieldBase (FieldBuilder, this);
5985 return true;
5988 public override void Emit()
5990 if (fi == null)
5991 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
5993 object[] fi_val = new object[1];
5994 fi_val [0] = buffer_size;
5996 CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor,
5997 ctor_args, fi, fi_val);
5998 fixed_buffer_type.SetCustomAttribute (cab);
6000 #if NET_2_0
6001 cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
6002 FieldBuilder.SetCustomAttribute (cab);
6003 #endif
6004 base.Emit ();
6007 protected override bool IsFieldClsCompliant {
6008 get {
6009 return false;
6013 #region IFixedField Members
6015 public FieldInfo Element {
6016 get {
6017 return element;
6021 public Type ElementType {
6022 get {
6023 return MemberType;
6027 #endregion
6031 // The Field class is used to represents class/struct fields during parsing.
6033 public class Field : FieldBase {
6034 // <summary>
6035 // Modifiers allowed in a class declaration
6036 // </summary>
6037 const int AllowedModifiers =
6038 Modifiers.NEW |
6039 Modifiers.PUBLIC |
6040 Modifiers.PROTECTED |
6041 Modifiers.INTERNAL |
6042 Modifiers.PRIVATE |
6043 Modifiers.STATIC |
6044 Modifiers.VOLATILE |
6045 Modifiers.UNSAFE |
6046 Modifiers.READONLY;
6048 public Field (DeclSpace parent, Expression type, int mod, string name,
6049 Attributes attrs, Location loc)
6050 : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
6051 attrs)
6055 public override bool Define ()
6057 if (!base.Define ())
6058 return false;
6060 if (RootContext.WarningLevel > 1){
6061 Type ptype = Parent.TypeBuilder.BaseType;
6063 // ptype is only null for System.Object while compiling corlib.
6064 if (ptype != null){
6065 TypeContainer.FindMembers (
6066 ptype, MemberTypes.Method,
6067 BindingFlags.Public |
6068 BindingFlags.Static | BindingFlags.Instance,
6069 System.Type.FilterName, Name);
6073 if ((ModFlags & Modifiers.VOLATILE) != 0){
6074 if (!MemberType.IsClass){
6075 Type vt = MemberType;
6077 if (TypeManager.IsEnumType (vt))
6078 vt = TypeManager.EnumToUnderlying (MemberType);
6080 if (!((vt == TypeManager.bool_type) ||
6081 (vt == TypeManager.sbyte_type) ||
6082 (vt == TypeManager.byte_type) ||
6083 (vt == TypeManager.short_type) ||
6084 (vt == TypeManager.ushort_type) ||
6085 (vt == TypeManager.int32_type) ||
6086 (vt == TypeManager.uint32_type) ||
6087 (vt == TypeManager.char_type) ||
6088 (vt == TypeManager.float_type) ||
6089 (!vt.IsValueType))){
6090 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
6091 GetSignatureForError (), TypeManager.CSharpName (vt));
6092 return false;
6096 if ((ModFlags & Modifiers.READONLY) != 0){
6097 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
6098 GetSignatureForError ());
6099 return false;
6103 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
6105 if (Parent.PartialContainer.Kind == Kind.Struct &&
6106 ((fa & FieldAttributes.Static) == 0) &&
6107 MemberType == Parent.TypeBuilder &&
6108 !TypeManager.IsBuiltinType (MemberType)){
6109 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
6110 "' causes a cycle in the structure layout");
6111 return false;
6114 try {
6115 FieldBuilder = Parent.TypeBuilder.DefineField (
6116 Name, MemberType, Modifiers.FieldAttr (ModFlags));
6118 TypeManager.RegisterFieldBase (FieldBuilder, this);
6120 catch (ArgumentException) {
6121 Report.Warning (-24, 1, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
6122 return false;
6125 if (initializer != null)
6126 Parent.PartialContainer.RegisterFieldForInitialization (this,
6127 new FieldInitializer (FieldBuilder, initializer, Parent));
6129 return true;
6132 protected override bool VerifyClsCompliance ()
6134 if (!base.VerifyClsCompliance ())
6135 return false;
6137 if ((ModFlags & Modifiers.VOLATILE) != 0) {
6138 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
6141 return true;
6146 // `set' and `get' accessors are represented with an Accessor.
6148 public class Accessor : IAnonymousHost {
6150 // Null if the accessor is empty, or a Block if not
6152 public const int AllowedModifiers =
6153 Modifiers.PUBLIC |
6154 Modifiers.PROTECTED |
6155 Modifiers.INTERNAL |
6156 Modifiers.PRIVATE;
6158 public ToplevelBlock Block;
6159 public Attributes Attributes;
6160 public Location Location;
6161 public int ModFlags;
6162 public bool Yields;
6163 public ArrayList AnonymousMethods;
6165 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
6167 Block = b;
6168 Attributes = attrs;
6169 Location = loc;
6170 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
6173 public void SetYields ()
6175 Yields = true;
6178 public void AddAnonymousMethod (AnonymousMethodExpression ame)
6180 if (AnonymousMethods == null)
6181 AnonymousMethods = new ArrayList ();
6182 AnonymousMethods.Add (ame);
6186 // Ooouh Martin, templates are missing here.
6187 // When it will be possible move here a lot of child code and template method type.
6188 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
6189 protected MethodData method_data;
6190 protected ToplevelBlock block;
6191 protected ListDictionary declarative_security;
6193 // The accessor are created event if they are not wanted.
6194 // But we need them because their names are reserved.
6195 // Field says whether accessor will be emited or not
6196 public readonly bool IsDummy;
6198 protected readonly string prefix;
6200 ReturnParameter return_attributes;
6202 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
6203 : base (member.Parent, SetupName (prefix, member, member.Location), null)
6205 this.prefix = prefix;
6206 IsDummy = true;
6209 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
6210 string prefix)
6211 : base (member.Parent, SetupName (prefix, member, accessor.Location),
6212 accessor.Attributes)
6214 this.prefix = prefix;
6215 this.block = accessor.Block;
6218 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
6220 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
6223 public void UpdateName (InterfaceMemberBase member)
6225 SetMemberName (SetupName (prefix, member, Location));
6228 #region IMethodData Members
6230 public abstract Iterator Iterator {
6231 get;
6234 public ToplevelBlock Block {
6235 get {
6236 return block;
6239 set {
6240 block = value;
6244 public CallingConventions CallingConventions {
6245 get {
6246 return CallingConventions.Standard;
6250 public bool IsExcluded ()
6252 return false;
6255 GenericMethod IMethodData.GenericMethod {
6256 get {
6257 return null;
6261 public MemberName MethodName {
6262 get {
6263 return MemberName;
6267 public Type[] ParameterTypes {
6268 get {
6269 return ParameterInfo.Types;
6273 public abstract Parameters ParameterInfo { get ; }
6274 public abstract Type ReturnType { get; }
6275 public abstract EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig);
6277 #endregion
6279 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
6281 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
6282 a.Type == TypeManager.conditional_attribute_type) {
6283 Report.Error (1667, a.Location,
6284 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
6285 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6286 return;
6289 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
6290 if (declarative_security == null)
6291 declarative_security = new ListDictionary ();
6292 a.ExtractSecurityPermissionSet (declarative_security);
6293 return;
6296 if (a.Target == AttributeTargets.Method) {
6297 method_data.MethodBuilder.SetCustomAttribute (cb);
6298 return;
6301 if (a.Target == AttributeTargets.ReturnValue) {
6302 if (return_attributes == null)
6303 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6305 return_attributes.ApplyAttributeBuilder (a, cb);
6306 return;
6309 ApplyToExtraTarget (a, cb);
6312 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
6314 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
6317 // It is not supported for the accessors
6318 public sealed override bool Define()
6320 throw new NotSupportedException ();
6323 public void Emit (DeclSpace parent)
6325 EmitMethod (parent);
6327 if (OptAttributes != null)
6328 OptAttributes.Emit ();
6330 if (declarative_security != null) {
6331 foreach (DictionaryEntry de in declarative_security) {
6332 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6336 block = null;
6339 protected virtual void EmitMethod (DeclSpace parent)
6341 method_data.Emit (parent);
6344 public override bool IsClsComplianceRequired()
6346 return false;
6349 public bool IsDuplicateImplementation (MethodCore method)
6351 if (!MemberName.Equals (method.MemberName))
6352 return false;
6354 Type[] param_types = method.ParameterTypes;
6356 if (param_types.Length != ParameterTypes.Length)
6357 return false;
6359 for (int i = 0; i < param_types.Length; i++)
6360 if (param_types [i] != ParameterTypes [i])
6361 return false;
6363 Report.SymbolRelatedToPreviousError (method);
6364 Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
6365 return true;
6368 public override bool IsUsed
6370 get {
6371 if (IsDummy)
6372 return false;
6374 return base.IsUsed;
6378 public new Location Location {
6379 get {
6380 return base.Location;
6384 public virtual bool ResolveMembers ()
6386 return true;
6390 // Represents header string for documentation comment.
6392 public override string DocCommentHeader {
6393 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6399 // Properties and Indexers both generate PropertyBuilders, we use this to share
6400 // their common bits.
6402 abstract public class PropertyBase : PropertyBasedMember {
6404 public class GetMethod : PropertyMethod
6406 static string[] attribute_targets = new string [] { "method", "return" };
6408 public GetMethod (PropertyBase method):
6409 base (method, "get_")
6413 public GetMethod (PropertyBase method, Accessor accessor):
6414 base (method, accessor, "get_")
6418 public override MethodBuilder Define (DeclSpace parent)
6420 base.Define (parent);
6422 method_data = new MethodData (method, ModFlags, flags, this);
6424 if (!method_data.Define (parent))
6425 return null;
6427 return method_data.MethodBuilder;
6430 public override Type ReturnType {
6431 get {
6432 return method.MemberType;
6436 public override Parameters ParameterInfo {
6437 get {
6438 return Parameters.EmptyReadOnlyParameters;
6442 public override string[] ValidAttributeTargets {
6443 get {
6444 return attribute_targets;
6449 public class SetMethod : PropertyMethod {
6451 static string[] attribute_targets = new string [] { "method", "param", "return" };
6452 ImplicitParameter param_attr;
6453 protected Parameters parameters;
6455 public SetMethod (PropertyBase method):
6456 base (method, "set_")
6460 public SetMethod (PropertyBase method, Accessor accessor):
6461 base (method, accessor, "set_")
6465 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6467 if (a.Target == AttributeTargets.Parameter) {
6468 if (param_attr == null)
6469 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6471 param_attr.ApplyAttributeBuilder (a, cb);
6472 return;
6475 base.ApplyAttributeBuilder (a, cb);
6478 public override Parameters ParameterInfo {
6479 get {
6480 if (parameters == null)
6481 DefineParameters ();
6482 return parameters;
6486 protected virtual void DefineParameters ()
6488 parameters = new Parameters (
6489 new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
6490 new Type[] { method.MemberType });
6493 public override MethodBuilder Define (DeclSpace parent)
6495 if (IsDummy)
6496 return null;
6498 base.Define (parent);
6500 method_data = new MethodData (method, ModFlags, flags, this);
6502 if (!method_data.Define (parent))
6503 return null;
6505 return method_data.MethodBuilder;
6508 public override Type ReturnType {
6509 get {
6510 return TypeManager.void_type;
6514 public override string[] ValidAttributeTargets {
6515 get {
6516 return attribute_targets;
6521 static string[] attribute_targets = new string [] { "property" };
6523 public abstract class PropertyMethod : AbstractPropertyEventMethod
6525 protected readonly PropertyBase method;
6526 protected MethodAttributes flags;
6527 Iterator iterator;
6528 ArrayList anonymous_methods;
6529 bool yields;
6531 public PropertyMethod (PropertyBase method, string prefix)
6532 : base (method, prefix)
6534 this.method = method;
6537 public PropertyMethod (PropertyBase method, Accessor accessor,
6538 string prefix)
6539 : base (method, accessor, prefix)
6541 this.method = method;
6542 this.ModFlags = accessor.ModFlags;
6543 yields = accessor.Yields;
6544 anonymous_methods = accessor.AnonymousMethods;
6546 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6547 Report.FeatureIsNotISO1 (Location, "access modifiers on properties");
6551 public override Iterator Iterator {
6552 get { return iterator; }
6555 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6557 if (a.IsInternalMethodImplAttribute) {
6558 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
6559 method.is_external_implementation = true;
6562 base.ApplyAttributeBuilder (a, cb);
6565 public override AttributeTargets AttributeTargets {
6566 get {
6567 return AttributeTargets.Method;
6571 public override bool IsClsComplianceRequired ()
6573 return method.IsClsComplianceRequired ();
6576 public override bool ResolveMembers ()
6578 if (yields) {
6579 iterator = Iterator.CreateIterator (this, Parent, null, ModFlags);
6580 if (iterator == null)
6581 return false;
6584 if (anonymous_methods != null) {
6585 foreach (AnonymousMethodExpression ame in anonymous_methods) {
6586 if (!ame.CreateAnonymousHelpers ())
6587 return false;
6591 return true;
6594 public virtual MethodBuilder Define (DeclSpace parent)
6596 if (!method.CheckAbstractAndExtern (block != null))
6597 return null;
6599 TypeContainer container = parent.PartialContainer;
6602 // Check for custom access modifier
6604 if (ModFlags == 0) {
6605 ModFlags = method.ModFlags;
6606 flags = method.flags;
6607 } else {
6608 if (container.Kind == Kind.Interface)
6609 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6610 GetSignatureForError ());
6612 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6613 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6616 CheckModifiers (ModFlags);
6617 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6618 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6619 flags = Modifiers.MethodAttr (ModFlags);
6620 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6623 return null;
6626 public bool HasCustomAccessModifier
6628 get {
6629 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6633 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
6635 return new EmitContext (method,
6636 ds, method.ds, method.Location, ig, ReturnType,
6637 method.ModFlags, false);
6640 public override ObsoleteAttribute GetObsoleteAttribute ()
6642 return method.GetObsoleteAttribute ();
6645 public override string GetSignatureForError()
6647 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6650 void CheckModifiers (int modflags)
6652 int flags = 0;
6653 int mflags = method.ModFlags & Modifiers.Accessibility;
6655 if ((mflags & Modifiers.PUBLIC) != 0) {
6656 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6658 else if ((mflags & Modifiers.PROTECTED) != 0) {
6659 if ((mflags & Modifiers.INTERNAL) != 0)
6660 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6662 flags |= Modifiers.PRIVATE;
6664 else if ((mflags & Modifiers.INTERNAL) != 0)
6665 flags |= Modifiers.PRIVATE;
6667 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6668 Report.Error (273, Location,
6669 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6670 GetSignatureForError (), method.GetSignatureForError ());
6674 public override bool MarkForDuplicationCheck ()
6676 caching_flags |= Flags.TestMethodDuplication;
6677 return true;
6681 public PropertyMethod Get, Set;
6682 public PropertyBuilder PropertyBuilder;
6683 public MethodBuilder GetBuilder, SetBuilder;
6685 protected bool define_set_first = false;
6687 public PropertyBase (DeclSpace parent, Expression type, int mod_flags,
6688 int allowed_mod, bool is_iface, MemberName name,
6689 Attributes attrs, bool define_set_first)
6690 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name, attrs)
6692 this.define_set_first = define_set_first;
6695 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6697 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6698 a.Error_InvalidSecurityParent ();
6699 return;
6702 PropertyBuilder.SetCustomAttribute (cb);
6705 public override AttributeTargets AttributeTargets {
6706 get {
6707 return AttributeTargets.Property;
6711 public override bool Define ()
6713 if (!DoDefine ())
6714 return false;
6716 if (!IsTypePermitted ())
6717 return false;
6719 return true;
6722 protected override bool DoDefine ()
6724 if (!base.DoDefine ())
6725 return false;
6728 // Accessors modifiers check
6730 if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6731 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6732 GetSignatureForError ());
6733 return false;
6736 if ((Get.IsDummy || Set.IsDummy)
6737 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6738 Report.Error (276, Location,
6739 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6740 GetSignatureForError ());
6741 return false;
6744 if (MemberType.IsAbstract && MemberType.IsSealed) {
6745 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6746 return false;
6749 return true;
6752 bool DefineGet ()
6754 if (Get.IsDummy)
6755 return true;
6757 GetBuilder = Get.Define (Parent);
6758 return GetBuilder != null;
6761 bool DefineSet (bool define)
6763 if (!define || Set.IsDummy)
6764 return true;
6766 SetBuilder = Set.Define (Parent);
6767 return SetBuilder != null;
6770 protected bool DefineAccessors ()
6772 return DefineSet (define_set_first) &&
6773 DefineGet () &&
6774 DefineSet (!define_set_first);
6777 protected abstract PropertyInfo ResolveBaseProperty ();
6779 // TODO: rename to Resolve......
6780 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
6782 PropertyInfo base_property = ResolveBaseProperty ();
6783 if (base_property == null)
6784 return null;
6786 base_ret_type = base_property.PropertyType;
6787 MethodInfo get_accessor = base_property.GetGetMethod (true);
6788 MethodInfo set_accessor = base_property.GetSetMethod (true);
6789 MethodAttributes get_accessor_access, set_accessor_access;
6791 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6792 if (Get != null && !Get.IsDummy && get_accessor == null) {
6793 Report.SymbolRelatedToPreviousError (base_property);
6794 Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6797 if (Set != null && !Set.IsDummy && set_accessor == null) {
6798 Report.SymbolRelatedToPreviousError (base_property);
6799 Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6804 // Check base class accessors access
6807 // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
6808 get_accessor_access = set_accessor_access = 0;
6809 if ((ModFlags & Modifiers.NEW) == 0) {
6810 if (get_accessor != null) {
6811 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6812 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6814 if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6815 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access, ".get");
6818 if (set_accessor != null) {
6819 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6820 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6822 if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6823 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6827 // When one accessor does not exist and property hides base one
6828 // we need to propagate this upwards
6829 if (set_accessor == null)
6830 set_accessor = get_accessor;
6833 // Get the less restrictive access
6835 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6838 public override void Emit ()
6841 // The PropertyBuilder can be null for explicit implementations, in that
6842 // case, we do not actually emit the ".property", so there is nowhere to
6843 // put the attribute
6845 if (PropertyBuilder != null && OptAttributes != null)
6846 OptAttributes.Emit ();
6848 if (!Get.IsDummy)
6849 Get.Emit (Parent);
6851 if (!Set.IsDummy)
6852 Set.Emit (Parent);
6854 base.Emit ();
6857 /// <summary>
6858 /// Tests whether accessors are not in collision with some method (CS0111)
6859 /// </summary>
6860 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6862 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6865 public override bool IsUsed
6867 get {
6868 if (IsExplicitImpl)
6869 return true;
6871 return Get.IsUsed | Set.IsUsed;
6875 protected override void SetMemberName (MemberName new_name)
6877 base.SetMemberName (new_name);
6879 Get.UpdateName (this);
6880 Set.UpdateName (this);
6883 public override string[] ValidAttributeTargets {
6884 get {
6885 return attribute_targets;
6890 // Represents header string for documentation comment.
6892 public override string DocCommentHeader {
6893 get { return "P:"; }
6897 public class Property : PropertyBase {
6898 const int AllowedModifiers =
6899 Modifiers.NEW |
6900 Modifiers.PUBLIC |
6901 Modifiers.PROTECTED |
6902 Modifiers.INTERNAL |
6903 Modifiers.PRIVATE |
6904 Modifiers.STATIC |
6905 Modifiers.SEALED |
6906 Modifiers.OVERRIDE |
6907 Modifiers.ABSTRACT |
6908 Modifiers.UNSAFE |
6909 Modifiers.EXTERN |
6910 Modifiers.METHOD_YIELDS |
6911 Modifiers.VIRTUAL;
6913 const int AllowedInterfaceModifiers =
6914 Modifiers.NEW;
6916 public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
6917 MemberName name, Attributes attrs, Accessor get_block,
6918 Accessor set_block, bool define_set_first)
6919 : base (parent, type, mod,
6920 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6921 is_iface, name, attrs, define_set_first)
6923 if (get_block == null)
6924 Get = new GetMethod (this);
6925 else
6926 Get = new GetMethod (this, get_block);
6928 if (set_block == null)
6929 Set = new SetMethod (this);
6930 else
6931 Set = new SetMethod (this, set_block);
6934 public override bool Define ()
6936 if (!DoDefineBase ())
6937 return false;
6939 if (!base.Define ())
6940 return false;
6942 if (!CheckBase ())
6943 return false;
6945 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6947 if (!DefineAccessors ())
6948 return false;
6950 // FIXME - PropertyAttributes.HasDefault ?
6952 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6953 MemberName.ToString (), PropertyAttributes.None, MemberType, null);
6955 if (!Get.IsDummy)
6956 PropertyBuilder.SetGetMethod (GetBuilder);
6958 if (!Set.IsDummy)
6959 PropertyBuilder.SetSetMethod (SetBuilder);
6961 TypeManager.RegisterProperty (PropertyBuilder, this);
6962 return true;
6965 protected override PropertyInfo ResolveBaseProperty ()
6967 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
6968 Parent.TypeBuilder, Name, Parameters.EmptyReadOnlyParameters.Types, null, true) as PropertyInfo;
6972 /// </summary>
6973 /// Gigantic workaround for lameness in SRE follows :
6974 /// This class derives from EventInfo and attempts to basically
6975 /// wrap around the EventBuilder so that FindMembers can quickly
6976 /// return this in it search for members
6977 /// </summary>
6978 public class MyEventBuilder : EventInfo {
6981 // We use this to "point" to our Builder which is
6982 // not really a MemberInfo
6984 EventBuilder MyBuilder;
6987 // We "catch" and wrap these methods
6989 MethodInfo raise, remove, add;
6991 EventAttributes attributes;
6992 Type declaring_type, reflected_type, event_type;
6993 string name;
6995 Event my_event;
6997 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6999 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
7001 // And now store the values in our own fields.
7003 declaring_type = type_builder;
7005 reflected_type = type_builder;
7007 attributes = event_attr;
7008 this.name = name;
7009 my_event = ev;
7010 this.event_type = event_type;
7014 // Methods that you have to override. Note that you only need
7015 // to "implement" the variants that take the argument (those are
7016 // the "abstract" methods, the others (GetAddMethod()) are
7017 // regular.
7019 public override MethodInfo GetAddMethod (bool nonPublic)
7021 return add;
7024 public override MethodInfo GetRemoveMethod (bool nonPublic)
7026 return remove;
7029 public override MethodInfo GetRaiseMethod (bool nonPublic)
7031 return raise;
7035 // These methods make "MyEventInfo" look like a Builder
7037 public void SetRaiseMethod (MethodBuilder raiseMethod)
7039 raise = raiseMethod;
7040 MyBuilder.SetRaiseMethod (raiseMethod);
7043 public void SetRemoveOnMethod (MethodBuilder removeMethod)
7045 remove = removeMethod;
7046 MyBuilder.SetRemoveOnMethod (removeMethod);
7049 public void SetAddOnMethod (MethodBuilder addMethod)
7051 add = addMethod;
7052 MyBuilder.SetAddOnMethod (addMethod);
7055 public void SetCustomAttribute (CustomAttributeBuilder cb)
7057 MyBuilder.SetCustomAttribute (cb);
7060 public override object [] GetCustomAttributes (bool inherit)
7062 // FIXME : There's nothing which can be seemingly done here because
7063 // we have no way of getting at the custom attribute objects of the
7064 // EventBuilder !
7065 return null;
7068 public override object [] GetCustomAttributes (Type t, bool inherit)
7070 // FIXME : Same here !
7071 return null;
7074 public override bool IsDefined (Type t, bool b)
7076 return true;
7079 public override EventAttributes Attributes {
7080 get {
7081 return attributes;
7085 public override string Name {
7086 get {
7087 return name;
7091 public override Type DeclaringType {
7092 get {
7093 return declaring_type;
7097 public override Type ReflectedType {
7098 get {
7099 return reflected_type;
7103 public Type EventType {
7104 get {
7105 return event_type;
7109 public void SetUsed ()
7111 if (my_event != null) {
7112 // my_event.SetAssigned ();
7113 my_event.SetMemberIsUsed ();
7118 /// <summary>
7119 /// For case when event is declared like property (with add and remove accessors).
7120 /// </summary>
7121 public class EventProperty: Event {
7122 abstract class AEventPropertyAccessor : AEventAccessor
7124 readonly ArrayList anonymous_methods;
7126 public AEventPropertyAccessor (Event method, Accessor accessor, string prefix):
7127 base (method, accessor, prefix)
7129 this.anonymous_methods = accessor.AnonymousMethods;
7132 public override MethodBuilder Define (DeclSpace ds)
7134 method.CheckAbstractAndExtern (block != null);
7135 return base.Define (ds);
7138 public override bool ResolveMembers ()
7140 if (anonymous_methods == null)
7141 return true;
7143 foreach (AnonymousMethodExpression ame in anonymous_methods) {
7144 if (!ame.CreateAnonymousHelpers ())
7145 return false;
7148 return true;
7153 sealed class AddDelegateMethod: AEventPropertyAccessor
7155 public AddDelegateMethod (Event method, Accessor accessor):
7156 base (method, accessor, "add_")
7160 protected override MethodInfo DelegateMethodInfo {
7161 get {
7162 return TypeManager.delegate_combine_delegate_delegate;
7167 sealed class RemoveDelegateMethod: AEventPropertyAccessor
7169 public RemoveDelegateMethod (Event method, Accessor accessor):
7170 base (method, accessor, "remove_")
7174 protected override MethodInfo DelegateMethodInfo {
7175 get {
7176 return TypeManager.delegate_remove_delegate_delegate;
7182 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
7184 public EventProperty (DeclSpace parent, Expression type, int mod_flags,
7185 bool is_iface, MemberName name,
7186 Attributes attrs, Accessor add, Accessor remove)
7187 : base (parent, type, mod_flags, is_iface, name, attrs)
7189 Add = new AddDelegateMethod (this, add);
7190 Remove = new RemoveDelegateMethod (this, remove);
7193 public override bool Define()
7195 if (!base.Define ())
7196 return false;
7198 if (IsExplicitImpl)
7199 SetMemberIsUsed ();
7201 return true;
7204 public override string[] ValidAttributeTargets {
7205 get {
7206 return attribute_targets;
7211 /// <summary>
7212 /// Event is declared like field.
7213 /// </summary>
7214 public class EventField : Event {
7215 abstract class EventFieldAccessor : AEventAccessor
7217 protected EventFieldAccessor (Event method, string prefix)
7218 : base (method, prefix)
7222 protected override void EmitMethod(DeclSpace parent)
7224 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7225 return;
7227 MethodBuilder mb = method_data.MethodBuilder;
7228 ILGenerator ig = mb.GetILGenerator ();
7230 // TODO: because we cannot use generics yet
7231 FieldInfo field_info = ((EventField)method).FieldBuilder;
7233 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
7234 if ((method.ModFlags & Modifiers.STATIC) != 0) {
7235 ig.Emit (OpCodes.Ldsfld, field_info);
7236 ig.Emit (OpCodes.Ldarg_0);
7237 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7238 ig.Emit (OpCodes.Castclass, method.MemberType);
7239 ig.Emit (OpCodes.Stsfld, field_info);
7240 } else {
7241 ig.Emit (OpCodes.Ldarg_0);
7242 ig.Emit (OpCodes.Ldarg_0);
7243 ig.Emit (OpCodes.Ldfld, field_info);
7244 ig.Emit (OpCodes.Ldarg_1);
7245 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7246 ig.Emit (OpCodes.Castclass, method.MemberType);
7247 ig.Emit (OpCodes.Stfld, field_info);
7249 ig.Emit (OpCodes.Ret);
7253 sealed class AddDelegateMethod: EventFieldAccessor
7255 public AddDelegateMethod (Event method):
7256 base (method, "add_")
7260 protected override MethodInfo DelegateMethodInfo {
7261 get {
7262 return TypeManager.delegate_combine_delegate_delegate;
7267 sealed class RemoveDelegateMethod: EventFieldAccessor
7269 public RemoveDelegateMethod (Event method):
7270 base (method, "remove_")
7274 protected override MethodInfo DelegateMethodInfo {
7275 get {
7276 return TypeManager.delegate_remove_delegate_delegate;
7282 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
7283 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
7285 public FieldBuilder FieldBuilder;
7286 public Expression Initializer;
7288 public EventField (DeclSpace parent, Expression type, int mod_flags,
7289 bool is_iface, MemberName name,
7290 Attributes attrs)
7291 : base (parent, type, mod_flags, is_iface, name, attrs)
7293 Add = new AddDelegateMethod (this);
7294 Remove = new RemoveDelegateMethod (this);
7297 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7299 if (a.Target == AttributeTargets.Field) {
7300 FieldBuilder.SetCustomAttribute (cb);
7301 return;
7304 if (a.Target == AttributeTargets.Method) {
7305 int errors = Report.Errors;
7306 Add.ApplyAttributeBuilder (a, cb);
7307 if (errors == Report.Errors)
7308 Remove.ApplyAttributeBuilder (a, cb);
7309 return;
7312 base.ApplyAttributeBuilder (a, cb);
7315 public override bool Define()
7317 if (!base.Define ())
7318 return false;
7320 if (IsInterface)
7321 return true;
7323 // FIXME: We are unable to detect whether generic event is used because
7324 // we are using FieldExpr instead of EventExpr for event access in that
7325 // case. When this issue will be fixed this hack can be removed.
7326 if (TypeManager.IsGenericType (MemberType))
7327 SetMemberIsUsed();
7329 FieldBuilder = Parent.TypeBuilder.DefineField (
7330 Name, MemberType,
7331 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7332 TypeManager.RegisterEventField (EventBuilder, this);
7334 if (Initializer != null) {
7335 if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
7336 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
7337 GetSignatureForError ());
7338 return false;
7341 Parent.PartialContainer.RegisterFieldForInitialization (this,
7342 new FieldInitializer (FieldBuilder, Initializer, Parent));
7345 return true;
7348 public override string[] ValidAttributeTargets
7350 get {
7351 return IsInterface ? attribute_targets_interface : attribute_targets;
7356 public abstract class Event : PropertyBasedMember {
7357 public abstract class AEventAccessor : AbstractPropertyEventMethod
7359 protected readonly Event method;
7360 ImplicitParameter param_attr;
7362 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
7364 protected AEventAccessor (Event method, string prefix)
7365 : base (method, prefix)
7367 this.method = method;
7370 protected AEventAccessor (Event method, Accessor accessor, string prefix)
7371 : base (method, accessor, prefix)
7373 this.method = method;
7376 public override Iterator Iterator {
7377 get { return null; }
7380 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7382 if (a.IsInternalMethodImplAttribute) {
7383 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
7384 method.is_external_implementation = true;
7387 base.ApplyAttributeBuilder (a, cb);
7390 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
7392 if (a.Target == AttributeTargets.Parameter) {
7393 if (param_attr == null)
7394 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7396 param_attr.ApplyAttributeBuilder (a, cb);
7397 return;
7400 base.ApplyAttributeBuilder (a, cb);
7403 public override AttributeTargets AttributeTargets {
7404 get {
7405 return AttributeTargets.Method;
7409 public override bool IsClsComplianceRequired ()
7411 return method.IsClsComplianceRequired ();
7414 public virtual MethodBuilder Define (DeclSpace parent)
7416 method_data = new MethodData (method, method.ModFlags,
7417 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7419 if (!method_data.Define (parent))
7420 return null;
7422 MethodBuilder mb = method_data.MethodBuilder;
7423 ParameterInfo.ApplyAttributes (mb);
7424 return mb;
7427 protected abstract MethodInfo DelegateMethodInfo { get; }
7429 public override Type ReturnType {
7430 get {
7431 return TypeManager.void_type;
7435 public override EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
7437 return new EmitContext (
7438 ds, method.Parent, Location, ig, ReturnType,
7439 method.ModFlags, false);
7442 public override ObsoleteAttribute GetObsoleteAttribute ()
7444 return method.GetObsoleteAttribute ();
7447 public override string[] ValidAttributeTargets {
7448 get {
7449 return attribute_targets;
7453 public override Parameters ParameterInfo {
7454 get {
7455 return method.parameters;
7461 const int AllowedModifiers =
7462 Modifiers.NEW |
7463 Modifiers.PUBLIC |
7464 Modifiers.PROTECTED |
7465 Modifiers.INTERNAL |
7466 Modifiers.PRIVATE |
7467 Modifiers.STATIC |
7468 Modifiers.VIRTUAL |
7469 Modifiers.SEALED |
7470 Modifiers.OVERRIDE |
7471 Modifiers.UNSAFE |
7472 Modifiers.ABSTRACT |
7473 Modifiers.EXTERN;
7475 const int AllowedInterfaceModifiers =
7476 Modifiers.NEW;
7478 public AEventAccessor Add, Remove;
7479 public MyEventBuilder EventBuilder;
7480 public MethodBuilder AddBuilder, RemoveBuilder;
7482 Parameters parameters;
7484 protected Event (DeclSpace parent, Expression type, int mod_flags,
7485 bool is_iface, MemberName name, Attributes attrs)
7486 : base (parent, null, type, mod_flags,
7487 is_iface ? AllowedInterfaceModifiers : AllowedModifiers, is_iface,
7488 name, attrs)
7492 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7494 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
7495 a.Error_InvalidSecurityParent ();
7496 return;
7499 EventBuilder.SetCustomAttribute (cb);
7502 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7504 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7507 public override AttributeTargets AttributeTargets {
7508 get {
7509 return AttributeTargets.Event;
7513 public override bool Define ()
7515 if (!DoDefineBase ())
7516 return false;
7518 if (!DoDefine ())
7519 return false;
7521 if (!TypeManager.IsDelegateType (MemberType)) {
7522 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7523 return false;
7526 parameters = new Parameters (
7527 new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
7528 new Type[] { MemberType } );
7530 if (!CheckBase ())
7531 return false;
7534 // Now define the accessors
7537 AddBuilder = Add.Define (Parent);
7538 if (AddBuilder == null)
7539 return false;
7541 RemoveBuilder = Remove.Define (Parent);
7542 if (RemoveBuilder == null)
7543 return false;
7545 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
7546 EventBuilder.SetAddOnMethod (AddBuilder);
7547 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7548 return true;
7551 public override void Emit ()
7553 if (OptAttributes != null) {
7554 OptAttributes.Emit ();
7557 Add.Emit (Parent);
7558 Remove.Emit (Parent);
7560 base.Emit ();
7563 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
7565 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
7566 Parent.TypeBuilder, Name);
7568 if (mi == null)
7569 return null;
7571 ParameterData pd = TypeManager.GetParameterData (mi);
7572 base_ret_type = pd.ParameterType (0);
7573 return mi;
7577 // Represents header string for documentation comment.
7579 public override string DocCommentHeader {
7580 get { return "E:"; }
7585 public class Indexer : PropertyBase {
7587 class GetIndexerMethod : GetMethod
7589 public GetIndexerMethod (PropertyBase method):
7590 base (method)
7594 public GetIndexerMethod (PropertyBase method, Accessor accessor):
7595 base (method, accessor)
7599 public override Parameters ParameterInfo {
7600 get {
7601 return ((Indexer)method).parameters;
7606 class SetIndexerMethod: SetMethod
7608 public SetIndexerMethod (PropertyBase method):
7609 base (method)
7613 public SetIndexerMethod (PropertyBase method, Accessor accessor):
7614 base (method, accessor)
7618 protected override void DefineParameters ()
7620 parameters = Parameters.MergeGenerated (((Indexer)method).parameters,
7621 new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
7625 const int AllowedModifiers =
7626 Modifiers.NEW |
7627 Modifiers.PUBLIC |
7628 Modifiers.PROTECTED |
7629 Modifiers.INTERNAL |
7630 Modifiers.PRIVATE |
7631 Modifiers.VIRTUAL |
7632 Modifiers.SEALED |
7633 Modifiers.OVERRIDE |
7634 Modifiers.UNSAFE |
7635 Modifiers.EXTERN |
7636 Modifiers.ABSTRACT;
7638 const int AllowedInterfaceModifiers =
7639 Modifiers.NEW;
7641 public readonly Parameters parameters;
7643 public Indexer (DeclSpace parent, Expression type, MemberName name, int mod,
7644 bool is_iface, Parameters parameters, Attributes attrs,
7645 Accessor get_block, Accessor set_block, bool define_set_first)
7646 : base (parent, type, mod,
7647 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7648 is_iface, name, attrs, define_set_first)
7650 this.parameters = parameters;
7652 if (get_block == null)
7653 Get = new GetIndexerMethod (this);
7654 else
7655 Get = new GetIndexerMethod (this, get_block);
7657 if (set_block == null)
7658 Set = new SetIndexerMethod (this);
7659 else
7660 Set = new SetIndexerMethod (this, set_block);
7663 protected override bool CheckForDuplications ()
7665 ArrayList ar = Parent.PartialContainer.Indexers;
7666 if (ar != null) {
7667 int arLen = ar.Count;
7669 for (int i = 0; i < arLen; i++) {
7670 Indexer m = (Indexer) ar [i];
7671 if (IsDuplicateImplementation (m))
7672 return false;
7676 return true;
7679 bool IsDuplicateImplementation (Indexer indexer)
7681 if (this == indexer)
7682 return false;
7684 if (!MemberName.Equals (indexer.MemberName))
7685 return false;
7687 Type[] param_types = indexer.parameters.Types;
7689 // When it is not yet defined
7690 if (param_types == null)
7691 return false;
7693 if (param_types.Length != parameters.Count)
7694 return false;
7696 for (int i = 0; i < param_types.Length; i++)
7697 if (param_types [i] != parameters.Types [i])
7698 return false;
7700 Report.SymbolRelatedToPreviousError (indexer);
7701 Report.Error (111, Location, TypeContainer.Error111, indexer.GetSignatureForError ());
7702 return true;
7706 public override bool Define ()
7708 if (!DoDefineBase ())
7709 return false;
7711 if (!base.Define ())
7712 return false;
7714 if (!DefineParameters (parameters))
7715 return false;
7717 if (MemberType == TypeManager.void_type) {
7718 Report.Error (620, Location, "Indexers cannot have void type");
7719 return false;
7722 if (OptAttributes != null) {
7723 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
7724 if (indexer_attr != null) {
7725 // Remove the attribute from the list because it is not emitted
7726 OptAttributes.Attrs.Remove (indexer_attr);
7728 string name = indexer_attr.GetIndexerAttributeValue ();
7729 if (name == null)
7730 return false;
7732 ShortName = name;
7734 if (IsExplicitImpl) {
7735 Report.Error (415, indexer_attr.Location,
7736 "The `IndexerName' attribute is valid only on an " +
7737 "indexer that is not an explicit interface member declaration");
7738 return false;
7741 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7742 Report.Error (609, indexer_attr.Location,
7743 "Cannot set the `IndexerName' attribute on an indexer marked override");
7744 return false;
7749 if (InterfaceType != null) {
7750 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7751 if (base_IndexerName != Name)
7752 ShortName = base_IndexerName;
7755 if (!Parent.PartialContainer.AddMember (this) ||
7756 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
7757 return false;
7759 if (!CheckBase ())
7760 return false;
7762 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7764 if (!DefineAccessors ())
7765 return false;
7767 if (!Get.IsDummy) {
7768 // Setup iterator if we are one
7769 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
7770 Iterator iterator = Iterator.CreateIterator (Get, Parent, null, ModFlags);
7771 if (iterator == null)
7772 return false;
7777 // Now name the parameters
7779 Parameter [] p = parameters.FixedParameters;
7780 if (p != null) {
7781 // TODO: should be done in parser and it needs to do cycle
7782 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7783 CSharpParser.Error_ParameterModifierNotValid (Location);
7784 return false;
7788 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7789 Name, PropertyAttributes.None, MemberType, parameters.Types);
7791 if (!Get.IsDummy)
7792 PropertyBuilder.SetGetMethod (GetBuilder);
7794 if (!Set.IsDummy)
7795 PropertyBuilder.SetSetMethod (SetBuilder);
7797 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, parameters.Types);
7799 return true;
7802 public override string GetDocCommentName (DeclSpace ds)
7804 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
7807 public override string GetSignatureForError ()
7809 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7810 if (MemberName.Left != null) {
7811 sb.Append ('.');
7812 sb.Append (MemberName.Left);
7815 sb.Append (".this");
7816 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7817 return sb.ToString ();
7820 public override bool MarkForDuplicationCheck ()
7822 caching_flags |= Flags.TestMethodDuplication;
7823 return true;
7826 protected override PropertyInfo ResolveBaseProperty ()
7828 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
7829 Parent.TypeBuilder, Name, parameters.Types, null, true) as PropertyInfo;
7832 protected override bool VerifyClsCompliance ()
7834 if (!base.VerifyClsCompliance ())
7835 return false;
7837 parameters.VerifyClsCompliance ();
7838 return true;
7842 public class Operator : MethodOrOperator, IAnonymousHost {
7844 const int AllowedModifiers =
7845 Modifiers.PUBLIC |
7846 Modifiers.UNSAFE |
7847 Modifiers.EXTERN |
7848 Modifiers.STATIC;
7850 public enum OpType : byte {
7852 // Unary operators
7853 LogicalNot,
7854 OnesComplement,
7855 Increment,
7856 Decrement,
7857 True,
7858 False,
7860 // Unary and Binary operators
7861 Addition,
7862 Subtraction,
7864 UnaryPlus,
7865 UnaryNegation,
7867 // Binary operators
7868 Multiply,
7869 Division,
7870 Modulus,
7871 BitwiseAnd,
7872 BitwiseOr,
7873 ExclusiveOr,
7874 LeftShift,
7875 RightShift,
7876 Equality,
7877 Inequality,
7878 GreaterThan,
7879 LessThan,
7880 GreaterThanOrEqual,
7881 LessThanOrEqual,
7883 // Implicit and Explicit
7884 Implicit,
7885 Explicit,
7887 // Just because of enum
7891 public readonly OpType OperatorType;
7893 public Operator (DeclSpace parent, OpType type, Expression ret_type,
7894 int mod_flags, Parameters parameters,
7895 ToplevelBlock block, Attributes attrs, Location loc)
7896 : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
7897 new MemberName ("op_" + type.ToString(), loc), attrs, parameters)
7899 OperatorType = type;
7900 Block = block;
7903 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7905 if (a.Type == TypeManager.conditional_attribute_type) {
7906 Error_ConditionalAttributeIsNotValid ();
7907 return;
7910 base.ApplyAttributeBuilder (a, cb);
7913 protected override bool CheckForDuplications ()
7915 ArrayList ar = Parent.PartialContainer.Operators;
7916 if (ar != null) {
7917 int arLen = ar.Count;
7919 for (int i = 0; i < arLen; i++) {
7920 Operator o = (Operator) ar [i];
7921 if (IsDuplicateImplementation (o))
7922 return false;
7926 ar = Parent.PartialContainer.Methods;
7927 if (ar != null) {
7928 int arLen = ar.Count;
7930 for (int i = 0; i < arLen; i++) {
7931 Method m = (Method) ar [i];
7932 if (IsDuplicateImplementation (m))
7933 return false;
7937 return true;
7940 public override bool Define ()
7942 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7943 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7944 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7945 return false;
7948 // imlicit and explicit operator of same types are not allowed
7949 if (OperatorType == OpType.Explicit || OperatorType == OpType.Implicit)
7950 MarkForDuplicationCheck ();
7952 if (!base.Define ())
7953 return false;
7955 if (MemberType == TypeManager.void_type) {
7956 Report.Error (590, Location, "User-defined operators cannot return void");
7957 return false;
7960 Type declaring_type = MethodData.DeclaringType;
7961 Type return_type = MemberType;
7962 Type first_arg_type = ParameterTypes [0];
7964 // Rules for conversion operators
7966 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7967 if (first_arg_type == return_type && first_arg_type == declaring_type){
7968 Report.Error (555, Location,
7969 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7970 return false;
7973 if ((first_arg_type != declaring_type) && (return_type != declaring_type) &&
7974 !TypeManager.IsNullableTypeOf (first_arg_type, declaring_type) &&
7975 !TypeManager.IsNullableTypeOf (return_type, declaring_type)) {
7976 Report.Error (
7977 556, Location,
7978 "User-defined conversion must convert to or from the " +
7979 "enclosing type");
7980 return false;
7983 if (first_arg_type.IsInterface || return_type.IsInterface){
7984 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7985 GetSignatureForError ());
7986 return false;
7989 if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
7990 if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
7991 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
7992 GetSignatureForError ());
7993 return false;
7995 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
7996 GetSignatureForError ());
7997 return false;
7999 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
8000 if (first_arg_type != declaring_type || ParameterTypes [1] != TypeManager.int32_type) {
8001 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");
8002 return false;
8004 } else if (Parameters.Count == 1) {
8005 // Checks for Unary operators
8007 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
8008 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
8009 Report.Error (448, Location,
8010 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
8011 return false;
8013 if (first_arg_type != declaring_type) {
8014 Report.Error (
8015 559, Location, "The parameter type for ++ or -- operator must be the containing type");
8016 return false;
8020 if (first_arg_type != declaring_type){
8021 Report.Error (
8022 562, Location,
8023 "The parameter of a unary operator must be the " +
8024 "containing type");
8025 return false;
8028 if (OperatorType == OpType.True || OperatorType == OpType.False) {
8029 if (return_type != TypeManager.bool_type){
8030 Report.Error (
8031 215, Location,
8032 "The return type of operator True or False " +
8033 "must be bool");
8034 return false;
8038 } else {
8039 // Checks for Binary operators
8041 if (first_arg_type != declaring_type &&
8042 ParameterTypes [1] != declaring_type){
8043 Report.Error (
8044 563, Location,
8045 "One of the parameters of a binary operator must " +
8046 "be the containing type");
8047 return false;
8051 return true;
8054 protected override bool DoDefine ()
8056 if (!base.DoDefine ())
8057 return false;
8059 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
8060 return true;
8063 public override void Emit ()
8065 base.Emit ();
8067 Parameters.ApplyAttributes (MethodBuilder);
8070 // abstract or extern methods have no bodies
8072 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
8073 return;
8075 EmitContext ec;
8076 if ((flags & MethodAttributes.PinvokeImpl) == 0)
8077 ec = CreateEmitContext (Parent, MethodBuilder.GetILGenerator ());
8078 else
8079 ec = CreateEmitContext (Parent, null);
8081 SourceMethod source = SourceMethod.Create (Parent, MethodBuilder, Block);
8082 ec.EmitTopBlock (this, Block);
8084 if (source != null)
8085 source.CloseMethod ();
8087 Block = null;
8090 // Operator cannot be override
8091 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
8093 return null;
8096 public static string GetName (OpType ot)
8098 switch (ot){
8099 case OpType.LogicalNot:
8100 return "!";
8101 case OpType.OnesComplement:
8102 return "~";
8103 case OpType.Increment:
8104 return "++";
8105 case OpType.Decrement:
8106 return "--";
8107 case OpType.True:
8108 return "true";
8109 case OpType.False:
8110 return "false";
8111 case OpType.Addition:
8112 return "+";
8113 case OpType.Subtraction:
8114 return "-";
8115 case OpType.UnaryPlus:
8116 return "+";
8117 case OpType.UnaryNegation:
8118 return "-";
8119 case OpType.Multiply:
8120 return "*";
8121 case OpType.Division:
8122 return "/";
8123 case OpType.Modulus:
8124 return "%";
8125 case OpType.BitwiseAnd:
8126 return "&";
8127 case OpType.BitwiseOr:
8128 return "|";
8129 case OpType.ExclusiveOr:
8130 return "^";
8131 case OpType.LeftShift:
8132 return "<<";
8133 case OpType.RightShift:
8134 return ">>";
8135 case OpType.Equality:
8136 return "==";
8137 case OpType.Inequality:
8138 return "!=";
8139 case OpType.GreaterThan:
8140 return ">";
8141 case OpType.LessThan:
8142 return "<";
8143 case OpType.GreaterThanOrEqual:
8144 return ">=";
8145 case OpType.LessThanOrEqual:
8146 return "<=";
8147 case OpType.Implicit:
8148 return "implicit";
8149 case OpType.Explicit:
8150 return "explicit";
8151 default: return "";
8155 public static OpType GetOperatorType (string name)
8157 if (name.StartsWith ("op_")){
8158 for (int i = 0; i < Unary.oper_names.Length; ++i) {
8159 if (Unary.oper_names [i] == name)
8160 return (OpType)i;
8163 for (int i = 0; i < Binary.oper_names.Length; ++i) {
8164 if (Binary.oper_names [i] == name)
8165 return (OpType)i;
8168 return OpType.TOP;
8171 public override string GetSignatureForError ()
8173 StringBuilder sb = new StringBuilder ();
8174 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
8175 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
8177 else {
8178 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
8181 sb.Append (Parameters.GetSignatureForError ());
8182 return sb.ToString ();
8187 // This is used to compare method signatures
8189 struct MethodSignature {
8190 public string Name;
8191 public Type RetType;
8192 public Type [] Parameters;
8194 /// <summary>
8195 /// This delegate is used to extract methods which have the
8196 /// same signature as the argument
8197 /// </summary>
8198 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
8200 public MethodSignature (string name, Type ret_type, Type [] parameters)
8202 Name = name;
8203 RetType = ret_type;
8205 if (parameters == null)
8206 Parameters = Type.EmptyTypes;
8207 else
8208 Parameters = parameters;
8211 public override string ToString ()
8213 string pars = "";
8214 if (Parameters.Length != 0){
8215 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
8216 for (int i = 0; i < Parameters.Length; i++){
8217 sb.Append (Parameters [i]);
8218 if (i+1 < Parameters.Length)
8219 sb.Append (", ");
8221 pars = sb.ToString ();
8224 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
8227 public override int GetHashCode ()
8229 return Name.GetHashCode ();
8232 public override bool Equals (Object o)
8234 MethodSignature other = (MethodSignature) o;
8236 if (other.Name != Name)
8237 return false;
8239 if (other.RetType != RetType)
8240 return false;
8242 if (Parameters == null){
8243 if (other.Parameters == null)
8244 return true;
8245 return false;
8248 if (other.Parameters == null)
8249 return false;
8251 int c = Parameters.Length;
8252 if (other.Parameters.Length != c)
8253 return false;
8255 for (int i = 0; i < c; i++)
8256 if (other.Parameters [i] != Parameters [i])
8257 return false;
8259 return true;
8262 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8264 MethodSignature sig = (MethodSignature) filter_criteria;
8266 if (m.Name != sig.Name)
8267 return false;
8269 Type ReturnType;
8270 MethodInfo mi = m as MethodInfo;
8271 PropertyInfo pi = m as PropertyInfo;
8273 if (mi != null)
8274 ReturnType = mi.ReturnType;
8275 else if (pi != null)
8276 ReturnType = pi.PropertyType;
8277 else
8278 return false;
8281 // we use sig.RetType == null to mean `do not check the
8282 // method return value.
8284 if (sig.RetType != null)
8285 if (ReturnType != sig.RetType)
8286 return false;
8288 Type [] args;
8289 if (mi != null)
8290 args = TypeManager.GetParameterData (mi).Types;
8291 else
8292 args = TypeManager.GetArgumentTypes (pi);
8293 Type [] sigp = sig.Parameters;
8295 if (args.Length != sigp.Length)
8296 return false;
8298 for (int i = args.Length; i > 0; ){
8299 i--;
8300 if (args [i] != sigp [i])
8301 return false;
8303 return true;