2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
15 using System
.Collections
.Generic
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Runtime
.CompilerServices
;
19 using System
.Runtime
.InteropServices
;
20 using System
.Security
;
21 using System
.Security
.Permissions
;
26 using XmlElement
= System
.Object
;
31 using Mono
.CompilerServices
.SymbolWriter
;
33 namespace Mono
.CSharp
{
36 /// This is the base class for structs and classes.
38 public abstract class TypeContainer
: DeclSpace
, ITypeDefinition
41 // Different context is needed when resolving type container base
42 // types. Type names come from the parent scope but type parameter
43 // names from the container scope.
45 public struct BaseContext
: IMemberContext
49 public BaseContext (TypeContainer tc
)
54 #region IMemberContext Members
56 public CompilerContext Compiler
{
57 get { return tc.Compiler; }
60 public TypeSpec CurrentType
{
61 get { return tc.Parent.CurrentType; }
64 public TypeParameter
[] CurrentTypeParameters
{
65 get { return tc.PartialContainer.CurrentTypeParameters; }
68 public MemberCore CurrentMemberDefinition
{
72 public bool HasUnresolvedConstraints
{
76 public bool IsObsolete
{
77 get { return tc.IsObsolete; }
80 public bool IsUnsafe
{
81 get { return tc.IsUnsafe; }
84 public bool IsStatic
{
85 get { return tc.IsStatic; }
88 public string GetSignatureForError ()
90 return tc
.GetSignatureForError ();
93 public ExtensionMethodGroupExpr
LookupExtensionMethod (TypeSpec extensionType
, string name
, int arity
, Location loc
)
98 public FullNamedExpression
LookupNamespaceAlias (string name
)
100 return tc
.Parent
.LookupNamespaceAlias (name
);
103 public FullNamedExpression
LookupNamespaceOrType (string name
, int arity
, Location loc
, bool ignore_cs0104
)
106 TypeParameter
[] tp
= CurrentTypeParameters
;
108 TypeParameter t
= TypeParameter
.FindTypeParameter (tp
, name
);
110 return new TypeParameterExpr (t
, loc
);
114 return tc
.Parent
.LookupNamespaceOrType (name
, arity
, loc
, ignore_cs0104
);
124 GetHashCode
= 1 << 1,
125 HasStaticFieldInitializer
= 1 << 2
129 // Whether this is a struct, class or interface
130 public readonly MemberKind Kind
;
132 // Holds a list of classes and structures
133 protected List
<TypeContainer
> types
;
135 List
<MemberCore
> ordered_explicit_member_list
;
136 List
<MemberCore
> ordered_member_list
;
138 // Holds the list of properties
139 List
<MemberCore
> properties
;
141 // Holds the list of constructors
142 protected List
<Constructor
> instance_constructors
;
144 // Holds the list of fields
145 protected List
<FieldBase
> fields
;
147 // Holds a list of fields that have initializers
148 protected List
<FieldInitializer
> initialized_fields
;
150 // Holds a list of static fields that have initializers
151 protected List
<FieldInitializer
> initialized_static_fields
;
153 // Holds the list of constants
154 protected List
<MemberCore
> constants
;
156 // Holds the methods.
157 List
<MemberCore
> methods
;
160 protected List
<MemberCore
> events
;
162 // Holds the indexers
163 List
<MemberCore
> indexers
;
165 // Holds the operators
166 List
<MemberCore
> operators
;
168 // Holds the compiler generated classes
169 List
<CompilerGeneratedClass
> compiler_generated
;
172 // Pointers to the default constructor and the default static constructor
174 protected Constructor default_constructor
;
175 protected Constructor default_static_constructor
;
178 // Points to the first non-static field added to the container.
180 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
181 // and the first one's as good as any.
183 FieldBase first_nonstatic_field
= null;
186 // This one is computed after we can distinguish interfaces
187 // from classes from the arraylist `type_bases'
190 protected TypeExpr
[] iface_exprs
;
192 protected List
<FullNamedExpression
> type_bases
;
194 bool members_defined
;
195 bool members_defined_ok
;
198 TypeContainer InTransit
;
200 GenericTypeParameterBuilder
[] all_tp_builders
;
202 public const string DefaultIndexerName
= "Item";
204 private bool seen_normal_indexers
= false;
205 private string indexer_name
= DefaultIndexerName
;
206 protected bool requires_delayed_unmanagedtype_check
;
209 private CachedMethods cached_method
;
211 protected TypeSpec spec
;
212 TypeSpec current_type
;
214 List
<TypeContainer
> partial_parts
;
217 /// The pending methods that need to be implemented
218 // (interfaces or abstract methods)
220 PendingImplementation pending
;
222 public TypeContainer (NamespaceEntry ns
, DeclSpace parent
, MemberName name
,
223 Attributes attrs
, MemberKind kind
)
224 : base (ns
, parent
, name
, attrs
)
226 if (parent
!= null && parent
.NamespaceEntry
!= ns
)
227 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
230 this.PartialContainer
= this;
235 public override TypeSpec CurrentType
{
237 if (current_type
== null) {
240 // Switch to inflated version as it's used by all expressions
242 var targs
= CurrentTypeParameters
== null ? TypeSpec
.EmptyTypes
: CurrentTypeParameters
.Select (l
=> l
.Type
).ToArray ();
243 current_type
= spec
.MakeGenericType (targs
);
253 public override TypeParameter
[] CurrentTypeParameters
{
255 return PartialContainer
.type_params
;
259 int CurrentTypeParametersStartIndex
{
261 int total
= all_tp_builders
.Length
;
262 if (CurrentTypeParameters
!= null) {
263 return total
- CurrentTypeParameters
.Length
;
269 public TypeSpec Definition
{
275 public bool HasMembersDefined
{
277 return members_defined
;
283 public bool AddMember (MemberCore symbol
)
285 return AddToContainer (symbol
, symbol
.MemberName
.Basename
);
288 protected virtual bool AddMemberType (TypeContainer ds
)
290 return AddToContainer (ds
, ds
.Basename
);
293 protected virtual void RemoveMemberType (DeclSpace ds
)
295 RemoveFromContainer (ds
.Basename
);
298 public void AddConstant (Const constant
)
300 if (!AddMember (constant
))
303 if (constants
== null)
304 constants
= new List
<MemberCore
> ();
306 constants
.Add (constant
);
309 public TypeContainer
AddTypeContainer (TypeContainer tc
)
311 if (!AddMemberType (tc
))
315 types
= new List
<TypeContainer
> ();
321 public virtual TypeContainer
AddPartial (TypeContainer next_part
)
323 return AddPartial (next_part
, next_part
.Basename
);
326 protected TypeContainer
AddPartial (TypeContainer next_part
, string name
)
328 next_part
.ModFlags
|= Modifiers
.PARTIAL
;
329 TypeContainer tc
= GetDefinition (name
) as TypeContainer
;
331 return AddTypeContainer (next_part
);
333 if ((tc
.ModFlags
& Modifiers
.PARTIAL
) == 0) {
334 Report
.SymbolRelatedToPreviousError (next_part
);
335 Error_MissingPartialModifier (tc
);
338 if (tc
.Kind
!= next_part
.Kind
) {
339 Report
.SymbolRelatedToPreviousError (tc
);
340 Report
.Error (261, next_part
.Location
,
341 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
342 next_part
.GetSignatureForError ());
345 if ((tc
.ModFlags
& Modifiers
.AccessibilityMask
) != (next_part
.ModFlags
& Modifiers
.AccessibilityMask
) &&
346 ((tc
.ModFlags
& Modifiers
.DEFAULT_ACCESS_MODIFER
) == 0 &&
347 (next_part
.ModFlags
& Modifiers
.DEFAULT_ACCESS_MODIFER
) == 0)) {
348 Report
.SymbolRelatedToPreviousError (tc
);
349 Report
.Error (262, next_part
.Location
,
350 "Partial declarations of `{0}' have conflicting accessibility modifiers",
351 next_part
.GetSignatureForError ());
354 if (tc
.partial_parts
== null)
355 tc
.partial_parts
= new List
<TypeContainer
> (1);
357 if ((next_part
.ModFlags
& Modifiers
.DEFAULT_ACCESS_MODIFER
) != 0) {
358 tc
.ModFlags
|= next_part
.ModFlags
& ~
(Modifiers
.DEFAULT_ACCESS_MODIFER
| Modifiers
.AccessibilityMask
);
359 } else if ((tc
.ModFlags
& Modifiers
.DEFAULT_ACCESS_MODIFER
) != 0) {
360 tc
.ModFlags
&= ~
(Modifiers
.DEFAULT_ACCESS_MODIFER
| Modifiers
.AccessibilityMask
);
361 tc
.ModFlags
|= next_part
.ModFlags
;
363 tc
.ModFlags
|= next_part
.ModFlags
;
366 tc
.spec
.Modifiers
= tc
.ModFlags
;
368 if (next_part
.attributes
!= null) {
369 if (tc
.attributes
== null)
370 tc
.attributes
= next_part
.attributes
;
372 tc
.attributes
.AddAttributes (next_part
.attributes
.Attrs
);
375 next_part
.PartialContainer
= tc
;
376 tc
.partial_parts
.Add (next_part
);
380 public virtual void RemoveTypeContainer (TypeContainer next_part
)
383 types
.Remove (next_part
);
384 RemoveMemberType (next_part
);
387 public void AddDelegate (Delegate d
)
389 AddTypeContainer (d
);
392 private void AddMemberToList (MemberCore mc
, List
<MemberCore
> alist
, bool isexplicit
)
394 if (ordered_explicit_member_list
== null) {
395 ordered_explicit_member_list
= new List
<MemberCore
> ();
396 ordered_member_list
= new List
<MemberCore
> ();
400 if (Kind
== MemberKind
.Interface
) {
401 Report
.Error (541, mc
.Location
,
402 "`{0}': explicit interface declaration can only be declared in a class or struct",
403 mc
.GetSignatureForError ());
406 ordered_explicit_member_list
.Add (mc
);
407 alist
.Insert (0, mc
);
409 ordered_member_list
.Add (mc
);
415 public void AddMethod (MethodOrOperator method
)
417 if (!AddToContainer (method
, method
.MemberName
.Basename
))
421 methods
= new List
<MemberCore
> ();
423 if (method
.MemberName
.Left
!= null)
424 AddMemberToList (method
, methods
, true);
426 AddMemberToList (method
, methods
, false);
429 public void AddConstructor (Constructor c
)
431 bool is_static
= (c
.ModFlags
& Modifiers
.STATIC
) != 0;
432 if (!AddToContainer (c
, is_static
?
433 ConstructorBuilder
.ConstructorName
: ConstructorBuilder
.TypeConstructorName
))
436 if (is_static
&& c
.ParameterInfo
.IsEmpty
){
437 if (default_static_constructor
!= null) {
438 Report
.SymbolRelatedToPreviousError (default_static_constructor
);
439 Report
.Error (111, c
.Location
,
440 "A member `{0}' is already defined. Rename this member or use different parameter types",
441 c
.GetSignatureForError ());
445 default_static_constructor
= c
;
447 if (c
.ParameterInfo
.IsEmpty
)
448 default_constructor
= c
;
450 if (instance_constructors
== null)
451 instance_constructors
= new List
<Constructor
> ();
453 instance_constructors
.Add (c
);
457 public bool AddField (FieldBase field
)
459 if (!AddMember (field
))
463 fields
= new List
<FieldBase
> ();
467 if ((field
.ModFlags
& Modifiers
.STATIC
) != 0)
470 if (first_nonstatic_field
== null) {
471 first_nonstatic_field
= field
;
475 if (Kind
== MemberKind
.Struct
&& first_nonstatic_field
.Parent
!= field
.Parent
) {
476 Report
.SymbolRelatedToPreviousError (first_nonstatic_field
.Parent
);
477 Report
.Warning (282, 3, field
.Location
,
478 "struct instance field `{0}' found in different declaration from instance field `{1}'",
479 field
.GetSignatureForError (), first_nonstatic_field
.GetSignatureForError ());
484 public void AddProperty (Property prop
)
486 if (!AddMember (prop
) ||
487 !AddMember (prop
.Get
) || !AddMember (prop
.Set
))
490 if (properties
== null)
491 properties
= new List
<MemberCore
> ();
493 if (prop
.MemberName
.Left
!= null)
494 AddMemberToList (prop
, properties
, true);
496 AddMemberToList (prop
, properties
, false);
499 public void AddEvent (Event e
)
504 if (e
is EventProperty
) {
505 if (!AddMember (e
.Add
))
508 if (!AddMember (e
.Remove
))
513 events
= new List
<MemberCore
> ();
519 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
521 public void AddIndexer (Indexer i
)
523 if (indexers
== null)
524 indexers
= new List
<MemberCore
> ();
526 if (i
.IsExplicitImpl
)
527 AddMemberToList (i
, indexers
, true);
529 AddMemberToList (i
, indexers
, false);
532 public void AddOperator (Operator op
)
537 if (operators
== null)
538 operators
= new List
<MemberCore
> ();
543 public void AddCompilerGeneratedClass (CompilerGeneratedClass c
)
545 Report
.Debug (64, "ADD COMPILER GENERATED CLASS", this, c
);
547 if (compiler_generated
== null)
548 compiler_generated
= new List
<CompilerGeneratedClass
> ();
550 compiler_generated
.Add (c
);
553 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
555 if (a
.Type
== pa
.DefaultMember
) {
556 if (Indexers
!= null) {
557 Report
.Error (646, a
.Location
, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
562 if (a
.Type
== pa
.Required
) {
563 Report
.Error (1608, a
.Location
, "The RequiredAttribute attribute is not permitted on C# types");
567 TypeBuilder
.SetCustomAttribute ((ConstructorInfo
) ctor
.GetMetaInfo (), cdata
);
570 public override AttributeTargets AttributeTargets
{
572 throw new NotSupportedException ();
576 public IList
<TypeContainer
> Types
{
582 public IList
<MemberCore
> Methods
{
588 public IList
<MemberCore
> Constants
{
594 public virtual TypeSpec BaseType
{
596 return spec
.BaseType
;
600 public IList
<FieldBase
> Fields
{
606 public IList
<Constructor
> InstanceConstructors
{
608 return instance_constructors
;
612 public IList
<MemberCore
> Properties
{
618 public IList
<MemberCore
> Events
{
624 public IList
<MemberCore
> Indexers
{
630 public IList
<MemberCore
> Operators
{
636 public IList
<CompilerGeneratedClass
> CompilerGeneratedClasses
{
638 return compiler_generated
;
642 protected override TypeAttributes TypeAttr
{
644 return ModifiersExtensions
.TypeAttr (ModFlags
, IsTopLevel
) | base.TypeAttr
;
648 public int TypeParametersCount
{
650 return MemberName
.Arity
;
654 TypeParameterSpec
[] ITypeDefinition
.TypeParameters
{
656 // TODO MemberCache: this is going to hurt
657 return PartialContainer
.type_params
.Select (l
=> l
.Type
).ToArray ();
661 public string GetAttributeDefaultMember ()
663 return indexers
== null ? DefaultIndexerName
: indexer_name
;
666 public bool IsComImport
{
668 if (OptAttributes
== null)
671 return OptAttributes
.Contains (PredefinedAttributes
.Get
.ComImport
);
675 string ITypeDefinition
.Namespace
{
677 return NamespaceEntry
.NS
.MemberName
.GetSignatureForError ();
681 public virtual void RegisterFieldForInitialization (MemberCore field
, FieldInitializer expression
)
683 if ((field
.ModFlags
& Modifiers
.STATIC
) != 0){
684 if (initialized_static_fields
== null) {
685 PartialContainer
.HasStaticFieldInitializer
= true;
686 initialized_static_fields
= new List
<FieldInitializer
> (4);
689 initialized_static_fields
.Add (expression
);
691 if (initialized_fields
== null)
692 initialized_fields
= new List
<FieldInitializer
> (4);
694 initialized_fields
.Add (expression
);
698 public void ResolveFieldInitializers (BlockContext ec
)
700 if (partial_parts
!= null) {
701 foreach (TypeContainer part
in partial_parts
) {
702 part
.DoResolveFieldInitializers (ec
);
705 DoResolveFieldInitializers (ec
);
708 void DoResolveFieldInitializers (BlockContext ec
)
711 if (initialized_static_fields
== null)
714 bool has_complex_initializer
= !RootContext
.Optimize
;
716 ExpressionStatement
[] init
= new ExpressionStatement
[initialized_static_fields
.Count
];
717 for (i
= 0; i
< initialized_static_fields
.Count
; ++i
) {
718 FieldInitializer fi
= initialized_static_fields
[i
];
719 ExpressionStatement s
= fi
.ResolveStatement (ec
);
721 s
= EmptyExpressionStatement
.Instance
;
722 } else if (fi
.IsComplexInitializer
) {
723 has_complex_initializer
|= true;
729 for (i
= 0; i
< initialized_static_fields
.Count
; ++i
) {
730 FieldInitializer fi
= initialized_static_fields
[i
];
732 // Need special check to not optimize code like this
733 // static int a = b = 5;
736 if (!has_complex_initializer
&& fi
.IsDefaultInitializer
)
739 ec
.CurrentBlock
.AddScopeStatement (new StatementExpression (init
[i
]));
745 if (initialized_fields
== null)
748 for (int i
= 0; i
< initialized_fields
.Count
; ++i
) {
749 FieldInitializer fi
= (FieldInitializer
) initialized_fields
[i
];
750 ExpressionStatement s
= fi
.ResolveStatement (ec
);
755 // Field is re-initialized to its default value => removed
757 if (fi
.IsDefaultInitializer
&& RootContext
.Optimize
)
760 ec
.CurrentBlock
.AddScopeStatement (new StatementExpression (s
));
764 public override string DocComment
{
776 public PendingImplementation PendingImplementations
{
777 get { return pending; }
780 public TypeSpec
GetAttributeCoClass ()
782 if (OptAttributes
== null)
785 Attribute a
= OptAttributes
.Search (PredefinedAttributes
.Get
.CoClass
);
789 return a
.GetCoClassAttributeValue ();
792 public AttributeUsageAttribute
GetAttributeUsage (PredefinedAttribute pa
)
795 if (OptAttributes
!= null) {
796 a
= OptAttributes
.Search (pa
);
802 return a
.GetAttributeUsageAttribute ();
805 public virtual void AddBasesForPart (DeclSpace part
, List
<FullNamedExpression
> bases
)
807 // FIXME: get rid of partial_parts and store lists of bases of each part here
808 // assumed, not verified: 'part' is in 'partial_parts'
809 ((TypeContainer
) part
).type_bases
= bases
;
813 /// This function computes the Base class and also the
814 /// list of interfaces that the class or struct @c implements.
816 /// The return value is an array (might be null) of
817 /// interfaces implemented (as Types).
819 /// The @base_class argument is set to the base object or null
820 /// if this is `System.Object'.
822 protected virtual TypeExpr
[] ResolveBaseTypes (out TypeExpr base_class
)
825 if (type_bases
== null)
828 int count
= type_bases
.Count
;
829 TypeExpr
[] ifaces
= null;
830 var base_context
= new BaseContext (this);
831 for (int i
= 0, j
= 0; i
< count
; i
++){
832 FullNamedExpression fne
= type_bases
[i
];
834 TypeExpr fne_resolved
= fne
.ResolveAsTypeTerminal (base_context
, false);
835 if (fne_resolved
== null)
838 if (i
== 0 && Kind
== MemberKind
.Class
&& !fne_resolved
.Type
.IsInterface
) {
839 if (fne_resolved
.Type
== InternalType
.Dynamic
)
840 Report
.Error (1965, Location
, "Class `{0}' cannot derive from the dynamic type",
841 GetSignatureForError ());
843 base_class
= fne_resolved
;
848 ifaces
= new TypeExpr
[count
- i
];
850 if (fne_resolved
.Type
.IsInterface
) {
851 for (int ii
= 0; ii
< j
; ++ii
) {
852 if (TypeManager
.IsEqual (fne_resolved
.Type
, ifaces
[ii
].Type
)) {
853 Report
.Error (528, Location
, "`{0}' is already listed in interface list",
854 fne_resolved
.GetSignatureForError ());
859 if (Kind
== MemberKind
.Interface
&& !IsAccessibleAs (fne_resolved
.Type
)) {
860 Report
.Error (61, fne
.Location
,
861 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
862 fne_resolved
.GetSignatureForError (), GetSignatureForError ());
865 Report
.SymbolRelatedToPreviousError (fne_resolved
.Type
);
866 if (Kind
!= MemberKind
.Class
) {
867 Report
.Error (527, fne
.Location
, "Type `{0}' in interface list is not an interface", fne_resolved
.GetSignatureForError ());
868 } else if (base_class
!= null)
869 Report
.Error (1721, fne
.Location
, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
870 GetSignatureForError (), base_class
.GetSignatureForError (), fne_resolved
.GetSignatureForError ());
872 Report
.Error (1722, fne
.Location
, "`{0}': Base class `{1}' must be specified as first",
873 GetSignatureForError (), fne_resolved
.GetSignatureForError ());
877 ifaces
[j
++] = fne_resolved
;
883 TypeExpr
[] GetNormalPartialBases (ref TypeExpr base_class
)
885 var ifaces
= new List
<TypeExpr
> (0);
886 if (iface_exprs
!= null)
887 ifaces
.AddRange (iface_exprs
);
889 foreach (TypeContainer part
in partial_parts
) {
890 TypeExpr new_base_class
;
891 TypeExpr
[] new_ifaces
= part
.ResolveBaseTypes (out new_base_class
);
892 if (new_base_class
!= TypeManager
.system_object_expr
) {
893 if (base_class
== TypeManager
.system_object_expr
)
894 base_class
= new_base_class
;
896 if (new_base_class
!= null && !TypeManager
.IsEqual (new_base_class
.Type
, base_class
.Type
)) {
897 Report
.SymbolRelatedToPreviousError (base_class
.Location
, "");
898 Report
.Error (263, part
.Location
,
899 "Partial declarations of `{0}' must not specify different base classes",
900 part
.GetSignatureForError ());
907 if (new_ifaces
== null)
910 foreach (TypeExpr iface
in new_ifaces
) {
911 if (ifaces
.Contains (iface
))
918 if (ifaces
.Count
== 0)
921 return ifaces
.ToArray ();
925 // Checks that some operators come in pairs:
931 // They are matched based on the return type and the argument types
933 void CheckPairedOperators ()
935 bool has_equality_or_inequality
= false;
936 var operators
= this.operators
.ToArray ();
937 bool[] has_pair
= new bool[operators
.Length
];
939 for (int i
= 0; i
< operators
.Length
; ++i
) {
940 if (operators
[i
] == null)
943 Operator o_a
= (Operator
) operators
[i
];
944 Operator
.OpType o_type
= o_a
.OperatorType
;
945 if (o_type
== Operator
.OpType
.Equality
|| o_type
== Operator
.OpType
.Inequality
)
946 has_equality_or_inequality
= true;
948 Operator
.OpType matching_type
= o_a
.GetMatchingOperator ();
949 if (matching_type
== Operator
.OpType
.TOP
) {
954 for (int ii
= 0; ii
< operators
.Length
; ++ii
) {
955 Operator o_b
= (Operator
) operators
[ii
];
956 if (o_b
== null || o_b
.OperatorType
!= matching_type
)
959 if (!TypeManager
.IsEqual (o_a
.ReturnType
, o_b
.ReturnType
))
962 if (!TypeSpecComparer
.Default
.Equals (o_a
.ParameterTypes
, o_b
.ParameterTypes
))
968 // Used to ignore duplicate user conversions
974 for (int i
= 0; i
< operators
.Length
; ++i
) {
975 if (operators
[i
] == null || has_pair
[i
])
978 Operator o
= (Operator
) operators
[i
];
979 Report
.Error (216, o
.Location
,
980 "The operator `{0}' requires a matching operator `{1}' to also be defined",
981 o
.GetSignatureForError (), Operator
.GetName (o
.GetMatchingOperator ()));
984 if (has_equality_or_inequality
) {
985 if (Methods
== null || !HasEquals
)
986 Report
.Warning (660, 2, Location
, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
987 GetSignatureForError ());
989 if (Methods
== null || !HasGetHashCode
)
990 Report
.Warning (661, 2, Location
, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
991 GetSignatureForError ());
995 bool CreateTypeBuilder ()
998 // Sets .size to 1 for structs with no instance fields
1000 int type_size
= Kind
== MemberKind
.Struct
&& first_nonstatic_field
== null ? 1 : 0;
1003 if (GlobalRootNamespace
.Instance
.IsNamespace (Name
)) {
1004 Report
.Error (519, Location
, "`{0}' clashes with a predefined namespace", Name
);
1008 ModuleBuilder builder
= Module
.Compiled
.Builder
;
1009 TypeBuilder
= builder
.DefineType (Name
, TypeAttr
, null, type_size
);
1011 TypeBuilder builder
= Parent
.TypeBuilder
;
1013 TypeBuilder
= builder
.DefineNestedType (Basename
, TypeAttr
, null, type_size
);
1016 spec
.SetMetaInfo (TypeBuilder
);
1017 spec
.MemberCache
= new MemberCache (this);
1018 spec
.DeclaringType
= Parent
.CurrentType
;
1021 Parent
.MemberCache
.AddMember (spec
);
1024 string[] param_names
= new string[TypeParameters
.Length
];
1025 for (int i
= 0; i
< TypeParameters
.Length
; i
++)
1026 param_names
[i
] = TypeParameters
[i
].Name
;
1028 all_tp_builders
= TypeBuilder
.DefineGenericParameters (param_names
);
1030 int offset
= CurrentTypeParametersStartIndex
;
1031 for (int i
= offset
; i
< all_tp_builders
.Length
; i
++) {
1032 CurrentTypeParameters
[i
- offset
].Define (all_tp_builders
[i
], spec
);
1039 bool DefineBaseTypes ()
1041 iface_exprs
= ResolveBaseTypes (out base_type
);
1042 if (partial_parts
!= null) {
1043 iface_exprs
= GetNormalPartialBases (ref base_type
);
1046 var cycle
= CheckRecursiveDefinition (this);
1047 if (cycle
!= null) {
1048 Report
.SymbolRelatedToPreviousError (cycle
);
1049 if (this is Interface
) {
1050 Report
.Error (529, Location
,
1051 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1052 GetSignatureForError (), cycle
.GetSignatureForError ());
1054 Report
.Error (146, Location
,
1055 "Circular base class dependency involving `{0}' and `{1}'",
1056 GetSignatureForError (), cycle
.GetSignatureForError ());
1062 if (iface_exprs
!= null) {
1063 foreach (TypeExpr iface
in iface_exprs
) {
1064 // Prevents a crash, the interface might not have been resolved: 442144
1068 var iface_type
= iface
.Type
;
1070 if (!spec
.AddInterface (iface_type
))
1073 if (iface_type
.IsGeneric
&& spec
.Interfaces
!= null) {
1074 foreach (var prev_iface
in iface_exprs
) {
1075 if (prev_iface
== iface
)
1078 if (!TypeSpecComparer
.Unify
.IsEqual (iface_type
, prev_iface
.Type
))
1081 Report
.Error (695, Location
,
1082 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1083 GetSignatureForError (), prev_iface
.GetSignatureForError (), iface_type
.GetSignatureForError ());
1087 TypeBuilder
.AddInterfaceImplementation (iface_type
.GetMetaInfo ());
1089 // Ensure the base is always setup
1090 var compiled_iface
= iface_type
.MemberDefinition
as Interface
;
1091 if (compiled_iface
!= null) {
1092 // TODO: Need DefineBaseType only
1093 compiled_iface
.DefineType ();
1096 if (iface_type
.Interfaces
!= null) {
1097 var base_ifaces
= new List
<TypeSpec
> (iface_type
.Interfaces
);
1098 for (int i
= 0; i
< base_ifaces
.Count
; ++i
) {
1099 var ii_iface_type
= base_ifaces
[i
];
1100 if (spec
.AddInterface (ii_iface_type
)) {
1101 TypeBuilder
.AddInterfaceImplementation (ii_iface_type
.GetMetaInfo ());
1103 if (ii_iface_type
.Interfaces
!= null)
1104 base_ifaces
.AddRange (ii_iface_type
.Interfaces
);
1111 if (Kind
== MemberKind
.Interface
) {
1112 spec
.BaseType
= TypeManager
.object_type
;
1117 if (base_type
!= null)
1118 base_ts
= base_type
.Type
;
1119 else if (spec
.IsStruct
)
1120 base_ts
= TypeManager
.value_type
;
1121 else if (spec
.IsEnum
)
1122 base_ts
= TypeManager
.enum_type
;
1123 else if (spec
.IsDelegate
)
1124 base_ts
= TypeManager
.multicast_delegate_type
;
1128 if (base_ts
!= null) {
1129 spec
.BaseType
= base_ts
;
1131 // Set base type after type creation
1132 TypeBuilder
.SetParent (base_ts
.GetMetaInfo ());
1138 public virtual void DefineConstants ()
1140 if (constants
!= null) {
1141 foreach (Const c
in constants
) {
1146 if (instance_constructors
!= null) {
1147 foreach (MethodCore m
in instance_constructors
) {
1148 var p
= m
.ParameterInfo
;
1149 if (!p
.IsEmpty
&& p
[p
.Count
- 1].HasDefaultValue
) {
1150 var rc
= new ResolveContext (m
);
1151 p
.ResolveDefaultValues (rc
);
1156 if (methods
!= null) {
1157 foreach (MethodCore m
in methods
) {
1158 var p
= m
.ParameterInfo
;
1159 if (!p
.IsEmpty
&& p
[p
.Count
- 1].HasDefaultValue
) {
1160 var rc
= new ResolveContext (m
);
1161 p
.ResolveDefaultValues (rc
);
1166 if (indexers
!= null) {
1167 foreach (Indexer i
in indexers
) {
1168 var p
= i
.ParameterInfo
;
1169 if (p
[p
.Count
- 1].HasDefaultValue
) {
1170 var rc
= new ResolveContext (i
);
1171 p
.ResolveDefaultValues (rc
);
1176 if (types
!= null) {
1177 foreach (var t
in types
)
1178 t
.DefineConstants ();
1183 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1185 public TypeBuilder
CreateType ()
1187 if (TypeBuilder
!= null)
1193 if (!CreateTypeBuilder ()) {
1198 if (partial_parts
!= null) {
1199 foreach (TypeContainer part
in partial_parts
) {
1201 part
.current_type
= current_type
;
1202 part
.TypeBuilder
= TypeBuilder
;
1206 if (Types
!= null) {
1207 foreach (TypeContainer tc
in Types
) {
1208 if (tc
.CreateType () == null) {
1218 public override TypeBuilder
DefineType ()
1225 type_defined
= true;
1227 if (!DefineBaseTypes ()) {
1232 if (!DefineNestedTypes ()) {
1240 public override void SetParameterInfo (List
<Constraints
> constraints_list
)
1242 base.SetParameterInfo (constraints_list
);
1244 if (PartialContainer
.CurrentTypeParameters
== null || PartialContainer
== this)
1247 TypeParameter
[] tc_names
= PartialContainer
.CurrentTypeParameters
;
1248 for (int i
= 0; i
< tc_names
.Length
; ++i
) {
1249 if (tc_names
[i
].Name
!= type_params
[i
].Name
) {
1250 Report
.SymbolRelatedToPreviousError (PartialContainer
.Location
, "");
1251 Report
.Error (264, Location
, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1252 GetSignatureForError ());
1256 if (tc_names
[i
].Variance
!= type_params
[i
].Variance
) {
1257 Report
.SymbolRelatedToPreviousError (PartialContainer
.Location
, "");
1258 Report
.Error (1067, Location
, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1259 GetSignatureForError ());
1266 // Replaces normal spec with predefined one when compiling corlib
1267 // and this type container defines predefined type
1269 public void SetPredefinedSpec (PredefinedTypeSpec spec
)
1274 void UpdateTypeParameterConstraints (TypeContainer part
)
1276 TypeParameter
[] current_params
= type_params
;
1277 for (int i
= 0; i
< current_params
.Length
; i
++) {
1278 if (current_params
[i
].AddPartialConstraints (part
, part
.type_params
[i
]))
1281 Report
.SymbolRelatedToPreviousError (Location
, "");
1282 Report
.Error (265, part
.Location
,
1283 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1284 GetSignatureForError (), current_params
[i
].GetSignatureForError ());
1288 public bool ResolveTypeParameters ()
1290 if (!DoResolveTypeParameters ())
1293 if (types
!= null) {
1294 foreach (var type
in types
)
1295 if (!type
.ResolveTypeParameters ())
1299 if (compiler_generated
!= null) {
1300 foreach (CompilerGeneratedClass c
in compiler_generated
)
1301 if (!c
.ResolveTypeParameters ())
1308 protected virtual bool DoResolveTypeParameters ()
1310 if (CurrentTypeParameters
== null)
1313 if (PartialContainer
!= this)
1314 throw new InternalErrorException ();
1316 var base_context
= new BaseContext (this);
1317 foreach (TypeParameter type_param
in CurrentTypeParameters
) {
1318 if (!type_param
.ResolveConstraints (base_context
)) {
1324 if (partial_parts
!= null) {
1325 foreach (TypeContainer part
in partial_parts
)
1326 UpdateTypeParameterConstraints (part
);
1332 protected virtual bool DefineNestedTypes ()
1334 if (Types
!= null) {
1335 foreach (TypeContainer tc
in Types
)
1336 if (tc
.DefineType () == null)
1343 TypeSpec
CheckRecursiveDefinition (TypeContainer tc
)
1345 if (InTransit
!= null)
1350 if (base_type
!= null && base_type
.Type
!= null) {
1351 var ptc
= base_type
.Type
.MemberDefinition
as TypeContainer
;
1352 if (ptc
!= null && ptc
.CheckRecursiveDefinition (this) != null)
1353 return base_type
.Type
;
1356 if (iface_exprs
!= null) {
1357 foreach (TypeExpr iface
in iface_exprs
) {
1358 // the interface might not have been resolved, prevents a crash, see #442144
1361 var ptc
= iface
.Type
.MemberDefinition
as Interface
;
1362 if (ptc
!= null && ptc
.CheckRecursiveDefinition (this) != null)
1367 if (!IsTopLevel
&& Parent
.PartialContainer
.CheckRecursiveDefinition (this) != null)
1375 /// Populates our TypeBuilder with fields and methods
1377 public sealed override bool Define ()
1379 if (members_defined
)
1380 return members_defined_ok
;
1382 members_defined_ok
= DoDefineMembers ();
1383 members_defined
= true;
1385 if (types
!= null) {
1386 foreach (var nested
in types
)
1390 return members_defined_ok
;
1393 protected virtual bool DoDefineMembers ()
1395 if (iface_exprs
!= null) {
1396 foreach (TypeExpr iface
in iface_exprs
) {
1397 var iface_type
= iface
.Type
;
1399 // Ensure the base is always setup
1400 var compiled_iface
= iface_type
.MemberDefinition
as Interface
;
1401 if (compiled_iface
!= null)
1402 compiled_iface
.Define ();
1404 if (Kind
== MemberKind
.Interface
)
1405 MemberCache
.AddInterface (iface_type
);
1407 ObsoleteAttribute oa
= iface_type
.GetAttributeObsolete ();
1408 if (oa
!= null && !IsObsolete
)
1409 AttributeTester
.Report_ObsoleteMessage (oa
, iface
.GetSignatureForError (), Location
, Report
);
1411 GenericTypeExpr ct
= iface
as GenericTypeExpr
;
1413 // TODO: passing `this' is wrong, should be base type iface instead
1414 TypeManager
.CheckTypeVariance (ct
.Type
, Variance
.Covariant
, this);
1416 ct
.CheckConstraints (this);
1418 if (ct
.HasDynamicArguments ()) {
1419 Report
.Error (1966, iface
.Location
,
1420 "`{0}': cannot implement a dynamic interface `{1}'",
1421 GetSignatureForError (), iface
.GetSignatureForError ());
1428 if (base_type
!= null) {
1429 ObsoleteAttribute obsolete_attr
= base_type
.Type
.GetAttributeObsolete ();
1430 if (obsolete_attr
!= null && !IsObsolete
)
1431 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, base_type
.GetSignatureForError (), Location
, Report
);
1433 var ct
= base_type
as GenericTypeExpr
;
1435 ct
.CheckConstraints (this);
1437 var baseContainer
= base_type
.Type
.MemberDefinition
as ClassOrStruct
;
1438 if (baseContainer
!= null) {
1439 baseContainer
.Define ();
1442 // It can trigger define of this type (for generic types only)
1444 if (HasMembersDefined
)
1449 if (type_params
!= null) {
1450 foreach (var tp
in type_params
) {
1451 tp
.CheckGenericConstraints ();
1456 MemberSpec candidate
;
1457 var conflict_symbol
= MemberCache
.FindBaseMember (this, out candidate
);
1458 if (conflict_symbol
== null && candidate
== null) {
1459 if ((ModFlags
& Modifiers
.NEW
) != 0)
1460 Report
.Warning (109, 4, Location
, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1461 GetSignatureForError ());
1463 if ((ModFlags
& Modifiers
.NEW
) == 0) {
1464 if (candidate
== null)
1465 candidate
= conflict_symbol
;
1467 Report
.SymbolRelatedToPreviousError (candidate
);
1468 Report
.Warning (108, 2, Location
, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1469 GetSignatureForError (), candidate
.GetSignatureForError ());
1474 DefineContainerMembers (constants
);
1475 DefineContainerMembers (fields
);
1477 if (Kind
== MemberKind
.Struct
|| Kind
== MemberKind
.Class
) {
1478 pending
= PendingImplementation
.GetPendingImplementations (this);
1480 if (requires_delayed_unmanagedtype_check
) {
1481 requires_delayed_unmanagedtype_check
= false;
1482 foreach (FieldBase f
in fields
) {
1483 if (f
.MemberType
!= null && f
.MemberType
.IsPointer
)
1484 TypeManager
.VerifyUnmanaged (Compiler
, f
.MemberType
, f
.Location
);
1490 // Constructors are not in the defined_names array
1492 DefineContainerMembers (instance_constructors
);
1494 DefineContainerMembers (events
);
1495 DefineContainerMembers (ordered_explicit_member_list
);
1496 DefineContainerMembers (ordered_member_list
);
1498 if (operators
!= null) {
1499 DefineContainerMembers (operators
);
1500 CheckPairedOperators ();
1503 ComputeIndexerName();
1504 CheckEqualsAndGetHashCode();
1509 protected virtual void DefineContainerMembers (System
.Collections
.IList mcal
) // IList<MemberCore>
1512 foreach (MemberCore mc
in mcal
) {
1515 } catch (Exception e
) {
1516 throw new InternalErrorException (mc
, e
);
1522 protected virtual void ComputeIndexerName ()
1524 if (indexers
== null)
1527 string class_indexer_name
= null;
1530 // If there's both an explicit and an implicit interface implementation, the
1531 // explicit one actually implements the interface while the other one is just
1532 // a normal indexer. See bug #37714.
1535 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1536 foreach (Indexer i
in indexers
) {
1537 if (i
.InterfaceType
!= null) {
1538 if (seen_normal_indexers
)
1539 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1543 seen_normal_indexers
= true;
1545 if (class_indexer_name
== null) {
1546 class_indexer_name
= i
.ShortName
;
1550 if (i
.ShortName
!= class_indexer_name
)
1551 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");
1554 if (class_indexer_name
!= null)
1555 indexer_name
= class_indexer_name
;
1558 void EmitIndexerName ()
1560 if (!seen_normal_indexers
)
1563 PredefinedAttribute pa
= PredefinedAttributes
.Get
.DefaultMember
;
1564 if (pa
.Constructor
== null &&
1565 !pa
.ResolveConstructor (Location
, TypeManager
.string_type
))
1568 CustomAttributeBuilder cb
= new CustomAttributeBuilder (pa
.Constructor
, new string [] { GetAttributeDefaultMember () }
);
1569 TypeBuilder
.SetCustomAttribute (cb
);
1572 protected virtual void CheckEqualsAndGetHashCode ()
1574 if (methods
== null)
1577 if (HasEquals
&& !HasGetHashCode
) {
1578 Report
.Warning (659, 3, this.Location
, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1582 // Indicated whether container has StructLayout attribute set Explicit
1583 public bool HasExplicitLayout
{
1584 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1585 set { caching_flags |= Flags.HasExplicitLayout; }
1588 public bool HasStructLayout
{
1589 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1590 set { caching_flags |= Flags.HasStructLayout; }
1593 public MemberCache MemberCache
{
1595 return spec
.MemberCache
;
1599 void CheckMemberUsage (List
<MemberCore
> al
, string member_type
)
1604 foreach (MemberCore mc
in al
) {
1605 if ((mc
.ModFlags
& Modifiers
.AccessibilityMask
) != Modifiers
.PRIVATE
)
1608 if (!mc
.IsUsed
&& (mc
.caching_flags
& Flags
.Excluded
) == 0) {
1609 Report
.Warning (169, 3, mc
.Location
, "The private {0} `{1}' is never used", member_type
, mc
.GetSignatureForError ());
1614 public virtual void VerifyMembers ()
1617 // Check for internal or private fields that were never assigned
1619 if (Report
.WarningLevel
>= 3) {
1620 if (RootContext
.EnhancedWarnings
) {
1621 CheckMemberUsage (properties
, "property");
1622 CheckMemberUsage (methods
, "method");
1623 CheckMemberUsage (constants
, "constant");
1626 if (fields
!= null){
1627 bool is_type_exposed
= Kind
== MemberKind
.Struct
|| IsExposedFromAssembly ();
1628 foreach (FieldBase f
in fields
) {
1629 if ((f
.ModFlags
& Modifiers
.AccessibilityMask
) != Modifiers
.PRIVATE
) {
1630 if (is_type_exposed
)
1637 if ((f
.caching_flags
& Flags
.IsAssigned
) == 0)
1638 Report
.Warning (169, 3, f
.Location
, "The private field `{0}' is never used", f
.GetSignatureForError ());
1640 Report
.Warning (414, 3, f
.Location
, "The private field `{0}' is assigned but its value is never used",
1641 f
.GetSignatureForError ());
1647 // Only report 649 on level 4
1649 if (Report
.WarningLevel
< 4)
1652 if ((f
.caching_flags
& Flags
.IsAssigned
) != 0)
1656 // Don't be pendatic over serializable attributes
1658 if (f
.OptAttributes
!= null || PartialContainer
.HasStructLayout
)
1661 Constant c
= New
.Constantify (f
.MemberType
);
1662 Report
.Warning (649, 4, f
.Location
, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
1663 f
.GetSignatureForError (), c
== null ? "null" : c
.AsString ());
1669 public override void Emit ()
1671 if (all_tp_builders
!= null) {
1672 int current_starts_index
= CurrentTypeParametersStartIndex
;
1673 for (int i
= 0; i
< all_tp_builders
.Length
; i
++) {
1674 if (i
< current_starts_index
) {
1675 TypeParameters
[i
].EmitConstraints (all_tp_builders
[i
]);
1677 CurrentTypeParameters
[i
- current_starts_index
].Emit ();
1682 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
1683 PredefinedAttributes
.Get
.CompilerGenerated
.EmitAttribute (TypeBuilder
);
1688 // TODO: move to ClassOrStruct
1689 void EmitConstructors ()
1691 if (instance_constructors
== null)
1694 if (spec
.IsAttribute
&& IsExposedFromAssembly () && RootContext
.VerifyClsCompliance
&& IsClsComplianceRequired ()) {
1695 bool has_compliant_args
= false;
1697 foreach (Constructor c
in instance_constructors
) {
1701 catch (Exception e
) {
1702 throw new InternalErrorException (c
, e
);
1705 if (has_compliant_args
)
1708 has_compliant_args
= c
.HasCompliantArgs
;
1710 if (!has_compliant_args
)
1711 Report
.Warning (3015, 1, Location
, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
1713 foreach (Constructor c
in instance_constructors
) {
1717 catch (Exception e
) {
1718 throw new InternalErrorException (c
, e
);
1725 /// Emits the code, this step is performed after all
1726 /// the types, enumerations, constructors
1728 public virtual void EmitType ()
1730 if (OptAttributes
!= null)
1731 OptAttributes
.Emit ();
1735 EmitConstructors ();
1737 if (constants
!= null)
1738 foreach (Const con
in constants
)
1741 if (default_static_constructor
!= null)
1742 default_static_constructor
.Emit ();
1744 if (operators
!= null)
1745 foreach (Operator o
in operators
)
1748 if (properties
!= null)
1749 foreach (Property p
in properties
)
1752 if (indexers
!= null) {
1753 foreach (Indexer indx
in indexers
)
1758 if (events
!= null){
1759 foreach (Event e
in Events
)
1763 if (methods
!= null) {
1764 for (int i
= 0; i
< methods
.Count
; ++i
)
1765 ((MethodOrOperator
) methods
[i
]).Emit ();
1769 foreach (FieldBase f
in fields
)
1772 if (types
!= null) {
1773 foreach (TypeContainer t
in types
)
1777 if (pending
!= null)
1778 pending
.VerifyPendingMethods (Report
);
1780 if (Report
.Errors
> 0)
1783 if (compiler_generated
!= null) {
1784 for (int i
= 0; i
< compiler_generated
.Count
; ++i
)
1785 compiler_generated
[i
].EmitType ();
1789 public void CloseType ()
1791 if ((caching_flags
& Flags
.CloseTypeCreated
) != 0)
1794 // Close base type container first to avoid TypeLoadException
1795 if (spec
.BaseType
!= null) {
1796 var btype
= spec
.BaseType
.MemberDefinition
as TypeContainer
;
1802 caching_flags
|= Flags
.CloseTypeCreated
;
1803 TypeBuilder
.CreateType ();
1804 } catch (TypeLoadException
){
1806 // This is fine, the code still created the type
1808 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1809 // Console.WriteLine (e.Message);
1810 } catch (Exception e
) {
1811 throw new InternalErrorException (this, e
);
1815 foreach (TypeContainer tc
in Types
)
1819 if (compiler_generated
!= null)
1820 foreach (CompilerGeneratedClass c
in compiler_generated
)
1825 initialized_fields
= null;
1826 initialized_static_fields
= null;
1828 ordered_explicit_member_list
= null;
1829 ordered_member_list
= null;
1834 compiler_generated
= null;
1835 default_constructor
= null;
1836 default_static_constructor
= null;
1838 OptAttributes
= null;
1842 // Performs the validation on a Method's modifiers (properties have
1843 // the same properties).
1845 public bool MethodModifiersValid (MemberCore mc
)
1847 const Modifiers vao
= (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
);
1848 const Modifiers va
= (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
);
1849 const Modifiers nv
= (Modifiers
.NEW
| Modifiers
.VIRTUAL
);
1851 var flags
= mc
.ModFlags
;
1854 // At most one of static, virtual or override
1856 if ((flags
& Modifiers
.STATIC
) != 0){
1857 if ((flags
& vao
) != 0){
1858 Report
.Error (112, mc
.Location
, "A static member `{0}' cannot be marked as override, virtual or abstract",
1859 mc
.GetSignatureForError ());
1864 if (Kind
== MemberKind
.Struct
){
1865 if ((flags
& va
) != 0){
1866 ModifiersExtensions
.Error_InvalidModifier (mc
.Location
, "virtual or abstract", Report
);
1871 if ((flags
& Modifiers
.OVERRIDE
) != 0 && (flags
& nv
) != 0){
1872 Report
.Error (113, mc
.Location
, "A member `{0}' marked as override cannot be marked as new or virtual",
1873 mc
.GetSignatureForError ());
1878 // If the declaration includes the abstract modifier, then the
1879 // declaration does not include static, virtual or extern
1881 if ((flags
& Modifiers
.ABSTRACT
) != 0){
1882 if ((flags
& Modifiers
.EXTERN
) != 0){
1884 180, mc
.Location
, "`{0}' cannot be both extern and abstract", mc
.GetSignatureForError ());
1888 if ((flags
& Modifiers
.SEALED
) != 0) {
1889 Report
.Error (502, mc
.Location
, "`{0}' cannot be both abstract and sealed", mc
.GetSignatureForError ());
1893 if ((flags
& Modifiers
.VIRTUAL
) != 0){
1894 Report
.Error (503, mc
.Location
, "The abstract method `{0}' cannot be marked virtual", mc
.GetSignatureForError ());
1898 if ((ModFlags
& Modifiers
.ABSTRACT
) == 0){
1899 Report
.SymbolRelatedToPreviousError (this);
1900 Report
.Error (513, mc
.Location
, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
1901 mc
.GetSignatureForError (), GetSignatureForError ());
1906 if ((flags
& Modifiers
.PRIVATE
) != 0){
1907 if ((flags
& vao
) != 0){
1908 Report
.Error (621, mc
.Location
, "`{0}': virtual or abstract members cannot be private", mc
.GetSignatureForError ());
1913 if ((flags
& Modifiers
.SEALED
) != 0){
1914 if ((flags
& Modifiers
.OVERRIDE
) == 0){
1915 Report
.Error (238, mc
.Location
, "`{0}' cannot be sealed because it is not an override", mc
.GetSignatureForError ());
1923 public Constructor DefaultStaticConstructor
{
1924 get { return default_static_constructor; }
1927 protected override bool VerifyClsCompliance ()
1929 if (!base.VerifyClsCompliance ())
1932 // Check this name against other containers
1933 NamespaceEntry
.NS
.VerifyClsCompliance ();
1935 // Check all container names for user classes
1936 if (Kind
!= MemberKind
.Delegate
)
1937 MemberCache
.VerifyClsCompliance (Definition
, Report
);
1939 if (BaseType
!= null && !BaseType
.IsCLSCompliant ()) {
1940 Report
.Warning (3009, 1, Location
, "`{0}': base type `{1}' is not CLS-compliant",
1941 GetSignatureForError (), BaseType
.GetSignatureForError ());
1947 /// Performs checks for an explicit interface implementation. First it
1948 /// checks whether the `interface_type' is a base inteface implementation.
1949 /// Then it checks whether `name' exists in the interface type.
1951 public bool VerifyImplements (InterfaceMemberBase mb
)
1953 var ifaces
= spec
.Interfaces
;
1954 if (ifaces
!= null) {
1955 foreach (TypeSpec t
in ifaces
){
1956 if (TypeManager
.IsEqual (t
, mb
.InterfaceType
))
1961 Report
.SymbolRelatedToPreviousError (mb
.InterfaceType
);
1962 Report
.Error (540, mb
.Location
, "`{0}': containing type does not implement interface `{1}'",
1963 mb
.GetSignatureForError (), TypeManager
.CSharpName (mb
.InterfaceType
));
1968 // Used for visiblity checks to tests whether this definition shares
1969 // base type baseType, it does member-definition search
1971 public bool IsBaseTypeDefinition (TypeSpec baseType
)
1973 // RootContext check
1974 if (TypeBuilder
== null)
1979 if (type
.MemberDefinition
== baseType
.MemberDefinition
)
1982 type
= type
.BaseType
;
1983 } while (type
!= null);
1988 public MemberCache
LoadMembers (TypeSpec declaringType
)
1990 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
1993 public void Mark_HasEquals ()
1995 cached_method
|= CachedMethods
.Equals
;
1998 public void Mark_HasGetHashCode ()
2000 cached_method
|= CachedMethods
.GetHashCode
;
2004 /// Method container contains Equals method
2006 public bool HasEquals
{
2008 return (cached_method
& CachedMethods
.Equals
) != 0;
2013 /// Method container contains GetHashCode method
2015 public bool HasGetHashCode
{
2017 return (cached_method
& CachedMethods
.GetHashCode
) != 0;
2021 public bool HasStaticFieldInitializer
{
2023 return (cached_method
& CachedMethods
.HasStaticFieldInitializer
) != 0;
2027 cached_method
|= CachedMethods
.HasStaticFieldInitializer
;
2029 cached_method
&= ~CachedMethods
.HasStaticFieldInitializer
;
2034 // Generates xml doc comments (if any), and if required,
2035 // handle warning report.
2037 internal override void GenerateDocComment (DeclSpace ds
)
2039 DocUtil
.GenerateTypeDocComment (this, ds
, Report
);
2042 public override string DocCommentHeader
{
2043 get { return "T:"; }
2047 public abstract class ClassOrStruct
: TypeContainer
2049 Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
2051 public ClassOrStruct (NamespaceEntry ns
, DeclSpace parent
,
2052 MemberName name
, Attributes attrs
, MemberKind kind
)
2053 : base (ns
, parent
, name
, attrs
, kind
)
2057 protected override bool AddToContainer (MemberCore symbol
, string name
)
2059 if (name
== MemberName
.Name
) {
2060 if (symbol
is TypeParameter
) {
2061 Report
.Error (694, symbol
.Location
,
2062 "Type parameter `{0}' has same name as containing type, or method",
2063 symbol
.GetSignatureForError ());
2067 InterfaceMemberBase imb
= symbol
as InterfaceMemberBase
;
2068 if (imb
== null || !imb
.IsExplicitImpl
) {
2069 Report
.SymbolRelatedToPreviousError (this);
2070 Report
.Error (542, symbol
.Location
, "`{0}': member names cannot be the same as their enclosing type",
2071 symbol
.GetSignatureForError ());
2076 return base.AddToContainer (symbol
, name
);
2079 public override void VerifyMembers ()
2081 base.VerifyMembers ();
2083 if ((events
!= null) && Report
.WarningLevel
>= 3) {
2084 foreach (Event e
in events
){
2085 // Note: The event can be assigned from same class only, so we can report
2086 // this warning for all accessibility modes
2087 if ((e
.caching_flags
& Flags
.IsUsed
) == 0)
2088 Report
.Warning (67, 3, e
.Location
, "The event `{0}' is never used", e
.GetSignatureForError ());
2093 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2095 if (a
.IsValidSecurityAttribute ()) {
2096 if (declarative_security
== null)
2097 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
2099 a
.ExtractSecurityPermissionSet (declarative_security
);
2103 if (a
.Type
== pa
.StructLayout
) {
2104 PartialContainer
.HasStructLayout
= true;
2106 if (a
.GetLayoutKindValue () == LayoutKind
.Explicit
)
2107 PartialContainer
.HasExplicitLayout
= true;
2110 if (a
.Type
== pa
.Dynamic
) {
2111 a
.Error_MisusedDynamicAttribute ();
2115 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2119 /// Defines the default constructors
2121 protected void DefineDefaultConstructor (bool is_static
)
2123 // The default instance constructor is public
2124 // If the class is abstract, the default constructor is protected
2125 // The default static constructor is private
2129 mods
= Modifiers
.STATIC
| Modifiers
.PRIVATE
;
2131 mods
= ((ModFlags
& Modifiers
.ABSTRACT
) != 0) ? Modifiers
.PROTECTED
: Modifiers
.PUBLIC
;
2134 Constructor c
= new Constructor (this, MemberName
.Name
, mods
,
2135 null, ParametersCompiled
.EmptyReadOnlyParameters
,
2136 new GeneratedBaseInitializer (Location
),
2140 c
.Block
= new ToplevelBlock (Compiler
, ParametersCompiled
.EmptyReadOnlyParameters
, Location
);
2143 protected override bool DoDefineMembers ()
2145 CheckProtectedModifier ();
2147 base.DoDefineMembers ();
2149 if (default_static_constructor
!= null)
2150 default_static_constructor
.Define ();
2155 public override void Emit ()
2157 if (default_static_constructor
== null && PartialContainer
.HasStaticFieldInitializer
) {
2158 DefineDefaultConstructor (true);
2159 default_static_constructor
.Define ();
2164 if (declarative_security
!= null) {
2165 foreach (var de
in declarative_security
) {
2166 TypeBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
2171 public override ExtensionMethodGroupExpr
LookupExtensionMethod (TypeSpec extensionType
, string name
, int arity
, Location loc
)
2173 DeclSpace top_level
= Parent
;
2174 if (top_level
!= null) {
2175 while (top_level
.Parent
!= null)
2176 top_level
= top_level
.Parent
;
2178 var candidates
= NamespaceEntry
.NS
.LookupExtensionMethod (extensionType
, this, name
, arity
);
2179 if (candidates
!= null)
2180 return new ExtensionMethodGroupExpr (candidates
, NamespaceEntry
, extensionType
, loc
);
2183 return NamespaceEntry
.LookupExtensionMethod (extensionType
, name
, arity
, loc
);
2186 protected override TypeAttributes TypeAttr
{
2188 if (default_static_constructor
== null)
2189 return base.TypeAttr
| TypeAttributes
.BeforeFieldInit
;
2191 return base.TypeAttr
;
2197 // TODO: should be sealed
2198 public class Class
: ClassOrStruct
{
2199 const Modifiers AllowedModifiers
=
2202 Modifiers
.PROTECTED
|
2203 Modifiers
.INTERNAL
|
2205 Modifiers
.ABSTRACT
|
2210 public const TypeAttributes StaticClassAttribute
= TypeAttributes
.Abstract
| TypeAttributes
.Sealed
;
2212 public Class (NamespaceEntry ns
, DeclSpace parent
, MemberName name
, Modifiers mod
,
2214 : base (ns
, parent
, name
, attrs
, MemberKind
.Class
)
2216 var accmods
= (Parent
== null || Parent
.Parent
== null) ? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
2217 this.ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod
, accmods
, Location
, Report
);
2218 spec
= new TypeSpec (Kind
, null, this, null, ModFlags
);
2220 if (IsStatic
&& RootContext
.Version
== LanguageVersion
.ISO_1
) {
2221 Report
.FeatureIsNotAvailable (Location
, "static classes");
2225 public override void AddBasesForPart (DeclSpace part
, List
<FullNamedExpression
> bases
)
2227 if (part
.Name
== "System.Object")
2228 Report
.Error (537, part
.Location
,
2229 "The class System.Object cannot have a base class or implement an interface.");
2230 base.AddBasesForPart (part
, bases
);
2233 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2235 if (a
.Type
== pa
.AttributeUsage
) {
2236 if (!BaseType
.IsAttribute
&& spec
!= TypeManager
.attribute_type
) {
2237 Report
.Error (641, a
.Location
, "Attribute `{0}' is only valid on classes derived from System.Attribute", a
.GetSignatureForError ());
2241 if (a
.Type
== pa
.Conditional
&& !BaseType
.IsAttribute
) {
2242 Report
.Error (1689, a
.Location
, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2246 if (a
.Type
== pa
.ComImport
&& !attributes
.Contains (pa
.Guid
)) {
2247 a
.Error_MissingGuidAttribute ();
2251 if (a
.Type
== pa
.Extension
) {
2252 a
.Error_MisusedExtensionAttribute ();
2256 if (a
.Type
.IsConditionallyExcluded (Location
))
2259 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2262 public override AttributeTargets AttributeTargets
{
2264 return AttributeTargets
.Class
;
2268 protected override void DefineContainerMembers (System
.Collections
.IList list
)
2274 base.DefineContainerMembers (list
);
2278 foreach (MemberCore m
in list
) {
2279 if (m
is Operator
) {
2280 Report
.Error (715, m
.Location
, "`{0}': Static classes cannot contain user-defined operators", m
.GetSignatureForError ());
2284 if (m
is Destructor
) {
2285 Report
.Error (711, m
.Location
, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2290 Report
.Error (720, m
.Location
, "`{0}': cannot declare indexers in a static class", m
.GetSignatureForError ());
2294 if ((m
.ModFlags
& Modifiers
.STATIC
) != 0 || m
is Enum
|| m
is Delegate
)
2297 if (m
is Constructor
) {
2298 Report
.Error (710, m
.Location
, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2302 Method method
= m
as Method
;
2303 if (method
!= null && method
.ParameterInfo
.HasExtensionMethodType
) {
2304 Report
.Error (1105, m
.Location
, "`{0}': Extension methods must be declared static", m
.GetSignatureForError ());
2308 Report
.Error (708, m
.Location
, "`{0}': cannot declare instance members in a static class", m
.GetSignatureForError ());
2311 base.DefineContainerMembers (list
);
2314 protected override bool DoDefineMembers ()
2316 if ((ModFlags
& Modifiers
.ABSTRACT
) == Modifiers
.ABSTRACT
&& (ModFlags
& (Modifiers
.SEALED
| Modifiers
.STATIC
)) != 0) {
2317 Report
.Error (418, Location
, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2320 if ((ModFlags
& (Modifiers
.SEALED
| Modifiers
.STATIC
)) == (Modifiers
.SEALED
| Modifiers
.STATIC
)) {
2321 Report
.Error (441, Location
, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2324 if (InstanceConstructors
== null && !IsStatic
)
2325 DefineDefaultConstructor (false);
2327 return base.DoDefineMembers ();
2330 public override void Emit ()
2334 if ((ModFlags
& Modifiers
.METHOD_EXTENSION
) != 0)
2335 PredefinedAttributes
.Get
.Extension
.EmitAttribute (TypeBuilder
);
2338 protected override TypeExpr
[] ResolveBaseTypes (out TypeExpr base_class
)
2340 TypeExpr
[] ifaces
= base.ResolveBaseTypes (out base_class
);
2342 if (base_class
== null) {
2343 if (spec
!= TypeManager
.object_type
)
2344 base_class
= TypeManager
.system_object_expr
;
2346 var base_type
= base_class
.Type
;
2348 if (base_type
.IsGenericParameter
){
2349 Report
.Error (689, base_class
.Location
, "`{0}': Cannot derive from type parameter `{1}'",
2350 GetSignatureForError (), base_type
.GetSignatureForError ());
2351 } else if (IsGeneric
&& base_type
.IsAttribute
) {
2352 Report
.Error (698, base_class
.Location
,
2353 "A generic type cannot derive from `{0}' because it is an attribute class",
2354 base_class
.GetSignatureForError ());
2355 } else if (base_type
.IsStatic
) {
2356 Report
.SymbolRelatedToPreviousError (base_class
.Type
);
2357 Report
.Error (709, Location
, "`{0}': Cannot derive from static class `{1}'",
2358 GetSignatureForError (), base_type
.GetSignatureForError ());
2359 } else if (base_type
.IsSealed
){
2360 Report
.SymbolRelatedToPreviousError (base_class
.Type
);
2361 Report
.Error (509, Location
, "`{0}': cannot derive from sealed type `{1}'",
2362 GetSignatureForError (), base_type
.GetSignatureForError ());
2365 if (base_type
is PredefinedTypeSpec
&& !(spec
is PredefinedTypeSpec
) &&
2366 (base_type
== TypeManager
.enum_type
|| base_type
== TypeManager
.value_type
|| base_type
== TypeManager
.multicast_delegate_type
||
2367 base_type
== TypeManager
.delegate_type
|| base_type
== TypeManager
.array_type
)) {
2368 Report
.Error (644, Location
, "`{0}' cannot derive from special class `{1}'",
2369 GetSignatureForError (), base_type
.GetSignatureForError ());
2370 base_class
= TypeManager
.system_object_expr
;
2373 if (!IsAccessibleAs (base_type
)) {
2374 Report
.SymbolRelatedToPreviousError (base_type
);
2375 Report
.Error (60, Location
, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2376 base_type
.GetSignatureForError (), GetSignatureForError ());
2380 if (PartialContainer
.IsStatic
) {
2381 if (base_class
.Type
!= TypeManager
.object_type
) {
2382 Report
.Error (713, Location
, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2383 GetSignatureForError (), base_class
.GetSignatureForError ());
2387 if (ifaces
!= null) {
2388 foreach (TypeExpr t
in ifaces
)
2389 Report
.SymbolRelatedToPreviousError (t
.Type
);
2390 Report
.Error (714, Location
, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2397 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2398 /// Valid only for attribute classes.
2399 public override string[] ConditionalConditions ()
2401 if ((caching_flags
& (Flags
.Excluded_Undetected
| Flags
.Excluded
)) == 0)
2404 caching_flags
&= ~Flags
.Excluded_Undetected
;
2406 if (OptAttributes
== null)
2409 Attribute
[] attrs
= OptAttributes
.SearchMulti (PredefinedAttributes
.Get
.Conditional
);
2413 string[] conditions
= new string[attrs
.Length
];
2414 for (int i
= 0; i
< conditions
.Length
; ++i
)
2415 conditions
[i
] = attrs
[i
].GetConditionalAttributeValue ();
2417 caching_flags
|= Flags
.Excluded
;
2422 // FIXME: How do we deal with the user specifying a different
2425 protected override TypeAttributes TypeAttr
{
2427 TypeAttributes ta
= base.TypeAttr
| TypeAttributes
.AutoLayout
| TypeAttributes
.Class
;
2429 ta
|= StaticClassAttribute
;
2435 public sealed class Struct
: ClassOrStruct
{
2437 bool is_unmanaged
, has_unmanaged_check_done
;
2441 // Modifiers allowed in a struct declaration
2443 const Modifiers AllowedModifiers
=
2446 Modifiers
.PROTECTED
|
2447 Modifiers
.INTERNAL
|
2451 public Struct (NamespaceEntry ns
, DeclSpace parent
, MemberName name
,
2452 Modifiers mod
, Attributes attrs
)
2453 : base (ns
, parent
, name
, attrs
, MemberKind
.Struct
)
2455 var accmods
= parent
.Parent
== null ? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
2456 this.ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod
, accmods
, Location
, Report
) | Modifiers
.SEALED
;
2457 spec
= new TypeSpec (Kind
, null, this, null, ModFlags
);
2460 public override AttributeTargets AttributeTargets
{
2462 return AttributeTargets
.Struct
;
2466 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2468 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2471 // When struct constains fixed fixed and struct layout has explicitly
2472 // set CharSet, its value has to be propagated to compiler generated
2473 // fixed field types
2475 if (a
.Type
== pa
.StructLayout
&& Fields
!= null && a
.HasField ("CharSet")) {
2476 for (int i
= 0; i
< Fields
.Count
; ++i
) {
2477 FixedField ff
= Fields
[i
] as FixedField
;
2479 ff
.SetCharSet (TypeBuilder
.Attributes
);
2484 bool CheckStructCycles (Struct s
)
2486 if (s
.Fields
== null)
2493 foreach (FieldBase field
in s
.Fields
) {
2494 TypeSpec ftype
= field
.Spec
.MemberType
;
2495 if (!ftype
.IsStruct
)
2498 if (ftype
is PredefinedTypeSpec
)
2501 foreach (var targ
in ftype
.TypeArguments
) {
2502 if (!CheckFieldTypeCycle (targ
)) {
2503 Report
.Error (523, field
.Location
,
2504 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2505 field
.GetSignatureForError (), ftype
.GetSignatureForError ());
2510 if ((field
.IsStatic
&& (!ftype
.IsGeneric
|| ftype
== CurrentType
)))
2513 if (!CheckFieldTypeCycle (ftype
)) {
2514 Report
.Error (523, field
.Location
,
2515 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2516 field
.GetSignatureForError (), ftype
.GetSignatureForError ());
2521 s
.InTransit
= false;
2525 bool CheckFieldTypeCycle (TypeSpec ts
)
2527 var fts
= ts
.MemberDefinition
as Struct
;
2531 return CheckStructCycles (fts
);
2534 public override void Emit ()
2536 CheckStructCycles (this);
2541 public override bool IsUnmanagedType ()
2546 if (has_unmanaged_check_done
)
2547 return is_unmanaged
;
2549 if (requires_delayed_unmanagedtype_check
)
2552 requires_delayed_unmanagedtype_check
= true;
2554 foreach (FieldBase f
in fields
) {
2558 // It can happen when recursive unmanaged types are defined
2559 // struct S { S* s; }
2560 TypeSpec mt
= f
.MemberType
;
2565 while (mt
.IsPointer
)
2566 mt
= TypeManager
.GetElementType (mt
);
2568 if (mt
.MemberDefinition
== this) {
2569 for (var p
= Parent
; p
!= null; p
= p
.Parent
) {
2570 if (p
.Kind
== MemberKind
.Class
) {
2571 has_unmanaged_check_done
= true;
2578 if (TypeManager
.IsUnmanagedType (mt
))
2581 has_unmanaged_check_done
= true;
2585 has_unmanaged_check_done
= true;
2586 is_unmanaged
= true;
2590 protected override TypeExpr
[] ResolveBaseTypes (out TypeExpr base_class
)
2592 TypeExpr
[] ifaces
= base.ResolveBaseTypes (out base_class
);
2593 base_class
= TypeManager
.system_valuetype_expr
;
2597 protected override TypeAttributes TypeAttr
{
2599 const TypeAttributes DefaultTypeAttributes
=
2600 TypeAttributes
.SequentialLayout
|
2601 TypeAttributes
.Sealed
;
2603 return base.TypeAttr
| DefaultTypeAttributes
;
2607 public override void RegisterFieldForInitialization (MemberCore field
, FieldInitializer expression
)
2609 if ((field
.ModFlags
& Modifiers
.STATIC
) == 0) {
2610 Report
.Error (573, field
.Location
, "`{0}': Structs cannot have instance field initializers",
2611 field
.GetSignatureForError ());
2614 base.RegisterFieldForInitialization (field
, expression
);
2622 public sealed class Interface
: TypeContainer
{
2625 /// Modifiers allowed in a class declaration
2627 public const Modifiers AllowedModifiers
=
2630 Modifiers
.PROTECTED
|
2631 Modifiers
.INTERNAL
|
2635 public Interface (NamespaceEntry ns
, DeclSpace parent
, MemberName name
, Modifiers mod
,
2637 : base (ns
, parent
, name
, attrs
, MemberKind
.Interface
)
2639 var accmods
= parent
.Parent
== null ? Modifiers
.INTERNAL
: Modifiers
.PRIVATE
;
2641 this.ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod
, accmods
, name
.Location
, Report
);
2642 spec
= new TypeSpec (Kind
, null, this, null, ModFlags
);
2645 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
2647 if (a
.Type
== pa
.ComImport
&& !attributes
.Contains (pa
.Guid
)) {
2648 a
.Error_MissingGuidAttribute ();
2652 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
2656 public override AttributeTargets AttributeTargets
{
2658 return AttributeTargets
.Interface
;
2662 protected override TypeAttributes TypeAttr
{
2664 const TypeAttributes DefaultTypeAttributes
=
2665 TypeAttributes
.AutoLayout
|
2666 TypeAttributes
.Abstract
|
2667 TypeAttributes
.Interface
;
2669 return base.TypeAttr
| DefaultTypeAttributes
;
2673 protected override bool VerifyClsCompliance ()
2675 if (!base.VerifyClsCompliance ())
2678 if (iface_exprs
!= null) {
2679 foreach (var iface
in iface_exprs
) {
2680 if (iface
.Type
.IsCLSCompliant ())
2683 Report
.SymbolRelatedToPreviousError (iface
.Type
);
2684 Report
.Warning (3027, 1, Location
, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2685 GetSignatureForError (), TypeManager
.CSharpName (iface
.Type
));
2693 public abstract class InterfaceMemberBase
: MemberBase
{
2695 // Whether this is an interface member.
2697 public bool IsInterface
;
2700 // If true, this is an explicit interface implementation
2702 public bool IsExplicitImpl
;
2704 protected bool is_external_implementation
;
2707 // The interface type we are explicitly implementing
2709 public TypeSpec InterfaceType
;
2712 // The method we're overriding if this is an override method.
2714 protected MethodSpec base_method
;
2716 readonly Modifiers explicit_mod_flags
;
2717 public MethodAttributes flags
;
2719 public InterfaceMemberBase (DeclSpace parent
, GenericMethod generic
,
2720 FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
,
2721 MemberName name
, Attributes attrs
)
2722 : base (parent
, generic
, type
, mod
, allowed_mod
, Modifiers
.PRIVATE
,
2725 IsInterface
= parent
.PartialContainer
.Kind
== MemberKind
.Interface
;
2726 IsExplicitImpl
= (MemberName
.Left
!= null);
2727 explicit_mod_flags
= mod
;
2730 protected override bool CheckBase ()
2732 if (!base.CheckBase ())
2735 if ((caching_flags
& Flags
.MethodOverloadsExist
) != 0)
2736 CheckForDuplications ();
2741 // For System.Object only
2742 if (Parent
.BaseType
== null)
2745 MemberSpec candidate
;
2746 var base_member
= FindBaseMember (out candidate
);
2748 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
2749 if (base_member
== null) {
2750 if (candidate
== null) {
2751 if (this is Method
&& ((Method
)this).ParameterInfo
.IsEmpty
&& MemberName
.Name
== Destructor
.MetadataName
&& MemberName
.Arity
== 0) {
2752 Report
.Error (249, Location
, "Do not override `{0}'. Use destructor syntax instead",
2753 "object.Finalize()");
2755 Report
.Error (115, Location
, "`{0}' is marked as an override but no suitable {1} found to override",
2756 GetSignatureForError (), SimpleName
.GetMemberType (this));
2759 Report
.SymbolRelatedToPreviousError (candidate
);
2761 Report
.Error (72, Location
, "`{0}': cannot override because `{1}' is not an event",
2762 GetSignatureForError (), TypeManager
.GetFullNameSignature (candidate
));
2763 else if (this is PropertyBase
)
2764 Report
.Error (544, Location
, "`{0}': cannot override because `{1}' is not a property",
2765 GetSignatureForError (), TypeManager
.GetFullNameSignature (candidate
));
2767 Report
.Error (505, Location
, "`{0}': cannot override because `{1}' is not a method",
2768 GetSignatureForError (), TypeManager
.GetFullNameSignature (candidate
));
2774 if (!CheckOverrideAgainstBase (base_member
))
2777 ObsoleteAttribute oa
= base_member
.GetAttributeObsolete ();
2779 if (OptAttributes
== null || !OptAttributes
.Contains (PredefinedAttributes
.Get
.Obsolete
)) {
2780 Report
.SymbolRelatedToPreviousError (base_member
);
2781 Report
.Warning (672, 1, Location
, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
2782 GetSignatureForError (), TypeManager
.GetFullNameSignature (base_member
));
2785 if (OptAttributes
!= null && OptAttributes
.Contains (PredefinedAttributes
.Get
.Obsolete
)) {
2786 Report
.SymbolRelatedToPreviousError (base_member
);
2787 Report
.Warning (809, 1, Location
, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
2788 GetSignatureForError (), TypeManager
.GetFullNameSignature (base_member
));
2792 base_method
= base_member
as MethodSpec
;
2796 if (base_member
== null && candidate
!= null && (!(candidate
is IParametersMember
) || !(this is IParametersMember
)))
2797 base_member
= candidate
;
2799 if (base_member
== null) {
2800 if ((ModFlags
& Modifiers
.NEW
) != 0) {
2801 if (base_member
== null) {
2802 Report
.Warning (109, 4, Location
, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2803 GetSignatureForError ());
2807 if ((ModFlags
& Modifiers
.NEW
) == 0) {
2808 ModFlags
|= Modifiers
.NEW
;
2809 Report
.SymbolRelatedToPreviousError (base_member
);
2810 if (!IsInterface
&& (base_member
.Modifiers
& (Modifiers
.ABSTRACT
| Modifiers
.VIRTUAL
| Modifiers
.OVERRIDE
)) != 0) {
2811 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",
2812 GetSignatureForError (), base_member
.GetSignatureForError ());
2814 Report
.Warning (108, 2, Location
, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2815 GetSignatureForError (), base_member
.GetSignatureForError ());
2819 if (!IsInterface
&& base_member
.IsAbstract
) {
2820 Report
.SymbolRelatedToPreviousError (base_member
);
2821 Report
.Error (533, Location
, "`{0}' hides inherited abstract member `{1}'",
2822 GetSignatureForError (), base_member
.GetSignatureForError ());
2829 protected virtual bool CheckForDuplications ()
2831 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, ParametersCompiled
.EmptyReadOnlyParameters
);
2835 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
2836 // that have been defined.
2838 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member
)
2842 if ((base_member
.Modifiers
& (Modifiers
.ABSTRACT
| Modifiers
.VIRTUAL
| Modifiers
.OVERRIDE
| Modifiers
.OVERRIDE_UNCHECKED
)) == 0) {
2843 Report
.SymbolRelatedToPreviousError (base_member
);
2844 Report
.Error (506, Location
,
2845 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
2846 GetSignatureForError (), TypeManager
.CSharpSignature (base_member
));
2850 // Now we check that the overriden method is not final
2851 if ((base_member
.Modifiers
& Modifiers
.SEALED
) != 0) {
2852 Report
.SymbolRelatedToPreviousError (base_member
);
2853 Report
.Error (239, Location
, "`{0}': cannot override inherited member `{1}' because it is sealed",
2854 GetSignatureForError (), TypeManager
.CSharpSignature (base_member
));
2858 var base_member_type
= ((IInterfaceMemberSpec
) base_member
).MemberType
;
2859 if (!TypeSpecComparer
.Override
.IsEqual (MemberType
, base_member_type
)) {
2860 Report
.SymbolRelatedToPreviousError (base_member
);
2861 if (this is PropertyBasedMember
) {
2862 Report
.Error (1715, Location
, "`{0}': type must be `{1}' to match overridden member `{2}'",
2863 GetSignatureForError (), TypeManager
.CSharpName (base_member_type
), TypeManager
.CSharpSignature (base_member
));
2865 Report
.Error (508, Location
, "`{0}': return type must be `{1}' to match overridden member `{2}'",
2866 GetSignatureForError (), TypeManager
.CSharpName (base_member_type
), TypeManager
.CSharpSignature (base_member
));
2874 protected static bool CheckAccessModifiers (MemberCore this_member
, MemberSpec base_member
)
2876 var thisp
= this_member
.ModFlags
& Modifiers
.AccessibilityMask
;
2877 var base_classp
= base_member
.Modifiers
& Modifiers
.AccessibilityMask
;
2879 if ((base_classp
& (Modifiers
.PROTECTED
| Modifiers
.INTERNAL
)) == (Modifiers
.PROTECTED
| Modifiers
.INTERNAL
)) {
2881 // when overriding protected internal, the method can be declared
2882 // protected internal only within the same assembly or assembly
2883 // which has InternalsVisibleTo
2885 if ((thisp
& (Modifiers
.PROTECTED
| Modifiers
.INTERNAL
)) == (Modifiers
.PROTECTED
| Modifiers
.INTERNAL
)) {
2886 return TypeManager
.IsThisOrFriendAssembly (this_member
.Assembly
, base_member
.Assembly
);
2888 if ((thisp
& Modifiers
.PROTECTED
) != Modifiers
.PROTECTED
) {
2890 // if it's not "protected internal", it must be "protected"
2895 if (this_member
.Parent
.PartialContainer
.Module
.Assembly
== base_member
.Assembly
) {
2897 // protected within the same assembly - an error
2901 if ((thisp
& ~
(Modifiers
.PROTECTED
| Modifiers
.INTERNAL
)) !=
2902 (base_classp
& ~
(Modifiers
.PROTECTED
| Modifiers
.INTERNAL
))) {
2904 // protected ok, but other attributes differ - report an error
2911 return thisp
== base_classp
;
2914 public override bool Define ()
2917 ModFlags
= Modifiers
.PUBLIC
| Modifiers
.ABSTRACT
|
2918 Modifiers
.VIRTUAL
| (ModFlags
& (Modifiers
.UNSAFE
| Modifiers
.NEW
));
2920 flags
= MethodAttributes
.Public
|
2921 MethodAttributes
.Abstract
|
2922 MethodAttributes
.HideBySig
|
2923 MethodAttributes
.NewSlot
|
2924 MethodAttributes
.Virtual
;
2926 Parent
.PartialContainer
.MethodModifiersValid (this);
2928 flags
= ModifiersExtensions
.MethodAttr (ModFlags
);
2931 if (IsExplicitImpl
) {
2932 TypeExpr iface_texpr
= MemberName
.Left
.GetTypeExpression ().ResolveAsTypeTerminal (Parent
, false);
2933 if (iface_texpr
== null)
2936 if ((ModFlags
& Modifiers
.PARTIAL
) != 0) {
2937 Report
.Error (754, Location
, "A partial method `{0}' cannot explicitly implement an interface",
2938 GetSignatureForError ());
2941 InterfaceType
= iface_texpr
.Type
;
2943 if (!InterfaceType
.IsInterface
) {
2944 Report
.SymbolRelatedToPreviousError (InterfaceType
);
2945 Report
.Error (538, Location
, "The type `{0}' in explicit interface declaration is not an interface",
2946 TypeManager
.CSharpName (InterfaceType
));
2948 Parent
.PartialContainer
.VerifyImplements (this);
2951 ModifiersExtensions
.Check (Modifiers
.AllowedExplicitImplFlags
, explicit_mod_flags
, 0, Location
, Report
);
2954 return base.Define ();
2957 protected bool DefineParameters (ParametersCompiled parameters
)
2959 if (!parameters
.Resolve (this))
2963 for (int i
= 0; i
< parameters
.Count
; ++i
) {
2964 Parameter p
= parameters
[i
];
2966 if (p
.HasDefaultValue
&& (IsExplicitImpl
|| this is Operator
|| (this is Indexer
&& parameters
.Count
== 1)))
2967 p
.Warning_UselessOptionalParameter (Report
);
2969 if (p
.CheckAccessibility (this))
2972 TypeSpec t
= parameters
.Types
[i
];
2973 Report
.SymbolRelatedToPreviousError (t
);
2974 if (this is Indexer
)
2975 Report
.Error (55, Location
,
2976 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
2977 TypeManager
.CSharpName (t
), GetSignatureForError ());
2978 else if (this is Operator
)
2979 Report
.Error (57, Location
,
2980 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
2981 TypeManager
.CSharpName (t
), GetSignatureForError ());
2983 Report
.Error (51, Location
,
2984 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
2985 TypeManager
.CSharpName (t
), GetSignatureForError ());
2991 public override void Emit()
2993 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
2994 // We are more strict than csc and report this as an error because SRE does not allow emit that
2995 if ((ModFlags
& Modifiers
.EXTERN
) != 0 && !is_external_implementation
) {
2996 if (this is Constructor
) {
2997 Report
.Error (824, Location
,
2998 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3000 Report
.Error (626, Location
,
3001 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3002 GetSignatureForError ());
3009 public override bool EnableOverloadChecks (MemberCore overload
)
3012 // Two members can differ in their explicit interface
3013 // type parameter only
3015 InterfaceMemberBase imb
= overload
as InterfaceMemberBase
;
3016 if (imb
!= null && imb
.IsExplicitImpl
) {
3017 if (IsExplicitImpl
) {
3018 caching_flags
|= Flags
.MethodOverloadsExist
;
3023 return IsExplicitImpl
;
3026 protected void Error_CannotChangeAccessModifiers (MemberCore member
, MemberSpec base_member
)
3028 Report
.SymbolRelatedToPreviousError (base_member
);
3029 Report
.Error (507, member
.Location
,
3030 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3031 member
.GetSignatureForError (),
3032 ModifiersExtensions
.AccessibilityName (base_member
.Modifiers
),
3033 base_member
.GetSignatureForError ());
3036 protected void Error_StaticReturnType ()
3038 Report
.Error (722, Location
,
3039 "`{0}': static types cannot be used as return types",
3040 MemberType
.GetSignatureForError ());
3044 /// Gets base method and its return type
3046 protected virtual MemberSpec
FindBaseMember (out MemberSpec bestCandidate
)
3048 return MemberCache
.FindBaseMember (this, out bestCandidate
);
3052 // The "short" name of this property / indexer / event. This is the
3053 // name without the explicit interface.
3055 public string ShortName
{
3056 get { return MemberName.Name; }
3057 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3061 // Returns full metadata method name
3063 public string GetFullName (MemberName name
)
3065 return GetFullName (name
.Name
);
3068 public string GetFullName (string name
)
3070 if (!IsExplicitImpl
)
3074 // When dealing with explicit members a full interface type
3075 // name is added to member name to avoid possible name conflicts
3077 // We use CSharpName which gets us full name with benefit of
3078 // replacing predefined names which saves some space and name
3081 return TypeManager
.CSharpName (InterfaceType
) + "." + name
;
3084 protected override bool VerifyClsCompliance ()
3086 if (!base.VerifyClsCompliance ()) {
3090 if (GenericMethod
!= null)
3091 GenericMethod
.VerifyClsCompliance ();
3096 public override bool IsUsed
3098 get { return IsExplicitImpl || base.IsUsed; }
3103 public abstract class MemberBase
: MemberCore
3105 protected FullNamedExpression type_expr
;
3106 protected TypeSpec member_type
;
3108 public readonly DeclSpace ds
;
3109 public readonly GenericMethod GenericMethod
;
3111 protected MemberBase (DeclSpace parent
, GenericMethod generic
,
3112 FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
, Modifiers def_mod
,
3113 MemberName name
, Attributes attrs
)
3114 : base (parent
, name
, attrs
)
3116 this.ds
= generic
!= null ? generic
: (DeclSpace
) parent
;
3117 this.type_expr
= type
;
3118 ModFlags
= ModifiersExtensions
.Check (allowed_mod
, mod
, def_mod
, Location
, Report
);
3119 GenericMethod
= generic
;
3120 if (GenericMethod
!= null)
3121 GenericMethod
.ModFlags
= ModFlags
;
3125 // Main member define entry
3127 public override bool Define ()
3129 DoMemberTypeIndependentChecks ();
3132 // Returns false only when type resolution failed
3134 if (!ResolveMemberType ())
3137 DoMemberTypeDependentChecks ();
3142 // Any type_name independent checks
3144 protected virtual void DoMemberTypeIndependentChecks ()
3146 if ((Parent
.ModFlags
& Modifiers
.SEALED
) != 0 &&
3147 (ModFlags
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
)) != 0) {
3148 Report
.Error (549, Location
, "New virtual member `{0}' is declared in a sealed class `{1}'",
3149 GetSignatureForError (), Parent
.GetSignatureForError ());
3154 // Any type_name dependent checks
3156 protected virtual void DoMemberTypeDependentChecks ()
3158 // verify accessibility
3159 if (!IsAccessibleAs (MemberType
)) {
3160 Report
.SymbolRelatedToPreviousError (MemberType
);
3161 if (this is Property
)
3162 Report
.Error (53, Location
,
3163 "Inconsistent accessibility: property type `" +
3164 TypeManager
.CSharpName (MemberType
) + "' is less " +
3165 "accessible than property `" + GetSignatureForError () + "'");
3166 else if (this is Indexer
)
3167 Report
.Error (54, Location
,
3168 "Inconsistent accessibility: indexer return type `" +
3169 TypeManager
.CSharpName (MemberType
) + "' is less " +
3170 "accessible than indexer `" + GetSignatureForError () + "'");
3171 else if (this is MethodCore
) {
3172 if (this is Operator
)
3173 Report
.Error (56, Location
,
3174 "Inconsistent accessibility: return type `" +
3175 TypeManager
.CSharpName (MemberType
) + "' is less " +
3176 "accessible than operator `" + GetSignatureForError () + "'");
3178 Report
.Error (50, Location
,
3179 "Inconsistent accessibility: return type `" +
3180 TypeManager
.CSharpName (MemberType
) + "' is less " +
3181 "accessible than method `" + GetSignatureForError () + "'");
3183 Report
.Error (52, Location
,
3184 "Inconsistent accessibility: field type `" +
3185 TypeManager
.CSharpName (MemberType
) + "' is less " +
3186 "accessible than field `" + GetSignatureForError () + "'");
3190 Variance variance
= this is Event
? Variance
.Contravariant
: Variance
.Covariant
;
3191 TypeManager
.CheckTypeVariance (MemberType
, variance
, this);
3194 protected bool IsTypePermitted ()
3196 if (TypeManager
.IsSpecialType (MemberType
)) {
3197 Report
.Error (610, Location
, "Field or property cannot be of type `{0}'", TypeManager
.CSharpName (MemberType
));
3203 protected virtual bool CheckBase ()
3205 CheckProtectedModifier ();
3210 public TypeSpec MemberType
{
3211 get { return member_type; }
3214 protected virtual bool ResolveMemberType ()
3216 if (member_type
!= null)
3217 throw new InternalErrorException ("Multi-resolve");
3219 TypeExpr te
= type_expr
.ResolveAsTypeTerminal (this, false);
3224 // Replace original type name, error reporting can use fully resolved name
3228 member_type
= te
.Type
;