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@gmail.com)
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-2011 Novell, Inc
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
16 using System.Collections.Generic;
17 using System.Runtime.InteropServices;
18 using System.Security;
19 using System.Security.Permissions;
22 using System.Diagnostics;
23 using Mono.CompilerServices.SymbolWriter;
26 using XmlElement = System.Object;
30 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
31 using IKVM.Reflection;
32 using IKVM.Reflection.Emit;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
42 // General types container, used as a base class for all constructs which can hold types
44 public abstract class TypeContainer : MemberCore
46 public readonly MemberKind Kind;
47 public readonly string Basename;
49 protected List<TypeContainer> containers;
51 TypeDefinition main_container;
53 protected Dictionary<string, MemberCore> defined_names;
55 protected bool is_defined;
57 public TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
58 : base (parent, name, attrs)
62 this.Basename = name.Basename;
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. User
98 public Attributes UnattachedAttributes {
102 public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 if (containers == null)
192 containers = new List<TypeContainer> ();
194 containers.Add (next_part);
197 public virtual void AddTypeContainer (TypeContainer tc)
201 var tparams = tc.MemberName.TypeParameters;
202 if (tparams != null && tc.PartialContainer != null) {
203 var td = (TypeDefinition) tc;
204 for (int i = 0; i < tparams.Count; ++i) {
206 if (tp.MemberName == null)
209 td.AddNameToContainer (tp, tp.Name);
214 public virtual void CloseContainer ()
216 if (containers != null) {
217 foreach (TypeContainer tc in containers) {
218 tc.CloseContainer ();
223 public virtual void CreateMetadataName (StringBuilder sb)
225 if (Parent != null && Parent.MemberName != null)
226 Parent.CreateMetadataName (sb);
228 MemberName.CreateMetadataName (sb);
231 public virtual bool CreateContainer ()
233 if (containers != null) {
234 foreach (TypeContainer tc in containers) {
235 tc.CreateContainer ();
242 public override bool Define ()
244 if (containers != null) {
245 foreach (TypeContainer tc in containers) {
250 // Release cache used by parser only
251 if (Module.Evaluator == null) {
252 defined_names = null;
254 defined_names.Clear ();
260 public virtual void PrepareEmit ()
262 if (containers != null) {
263 foreach (var t in containers) {
266 } catch (Exception e) {
267 if (MemberName == MemberName.Null)
270 throw new InternalErrorException (t, e);
276 public virtual bool DefineContainer ()
283 DoDefineContainer ();
285 if (containers != null) {
286 foreach (TypeContainer tc in containers) {
288 tc.DefineContainer ();
289 } catch (Exception e) {
290 if (MemberName == MemberName.Null)
293 throw new InternalErrorException (tc, e);
301 protected virtual void DefineNamespace ()
303 if (containers != null) {
304 foreach (var tc in containers) {
306 tc.DefineNamespace ();
307 } catch (Exception e) {
308 throw new InternalErrorException (tc, e);
314 protected virtual void DoDefineContainer ()
318 public virtual void EmitContainer ()
320 if (containers != null) {
321 for (int i = 0; i < containers.Count; ++i)
322 containers[i].EmitContainer ();
326 protected void Error_MissingPartialModifier (MemberCore type)
328 Report.Error (260, type.Location,
329 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
330 type.GetSignatureForError ());
333 public override string GetSignatureForDocumentation ()
335 if (Parent != null && Parent.MemberName != null)
336 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
338 return MemberName.GetSignatureForDocumentation ();
341 public override string GetSignatureForError ()
343 if (Parent != null && Parent.MemberName != null)
344 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
346 return MemberName.GetSignatureForError ();
349 public string GetSignatureForMetadata ()
352 var name = TypeNameParser.Escape (MemberName.Basename);
354 if (Parent is TypeDefinition) {
355 return Parent.GetSignatureForMetadata () + "+" + name;
358 if (Parent != null && Parent.MemberName != null)
359 return Parent.GetSignatureForMetadata () + "." + name;
363 throw new NotImplementedException ();
367 public virtual void RemoveContainer (TypeContainer cont)
369 if (containers != null)
370 containers.Remove (cont);
372 var tc = Parent == Module ? Module : this;
373 tc.defined_names.Remove (cont.Basename);
376 public virtual void VerifyMembers ()
378 if (containers != null) {
379 foreach (TypeContainer tc in containers)
384 public override void WriteDebugSymbol (MonoSymbolFile file)
386 if (containers != null) {
387 foreach (TypeContainer tc in containers) {
388 tc.WriteDebugSymbol (file);
394 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
397 // Different context is needed when resolving type container base
398 // types. Type names come from the parent scope but type parameter
399 // names from the container scope.
401 public struct BaseContext : IMemberContext
405 public BaseContext (TypeContainer tc)
410 #region IMemberContext Members
412 public CompilerContext Compiler {
413 get { return tc.Compiler; }
416 public TypeSpec CurrentType {
417 get { return tc.Parent.CurrentType; }
420 public TypeParameters CurrentTypeParameters {
421 get { return tc.PartialContainer.CurrentTypeParameters; }
424 public MemberCore CurrentMemberDefinition {
428 public bool IsObsolete {
429 get { return tc.IsObsolete; }
432 public bool IsUnsafe {
433 get { return tc.IsUnsafe; }
436 public bool IsStatic {
437 get { return tc.IsStatic; }
440 public ModuleContainer Module {
441 get { return tc.Module; }
444 public string GetSignatureForError ()
446 return tc.GetSignatureForError ();
449 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
454 public FullNamedExpression LookupNamespaceAlias (string name)
456 return tc.Parent.LookupNamespaceAlias (name);
459 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
462 var tp = CurrentTypeParameters;
464 TypeParameter t = tp.Find (name);
466 return new TypeParameterExpr (t, loc);
470 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
480 GetHashCode = 1 << 1,
481 HasStaticFieldInitializer = 1 << 2
484 readonly List<MemberCore> members;
486 // Holds a list of fields that have initializers
487 protected List<FieldInitializer> initialized_fields;
489 // Holds a list of static fields that have initializers
490 protected List<FieldInitializer> initialized_static_fields;
492 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
494 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
497 // Points to the first non-static field added to the container.
499 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
500 // and the first one's as good as any.
502 protected FieldBase first_nonstatic_field;
505 // This one is computed after we can distinguish interfaces
506 // from classes from the arraylist `type_bases'
508 protected TypeSpec base_type;
509 FullNamedExpression base_type_expr; // TODO: It's temporary variable
510 protected TypeSpec[] iface_exprs;
512 protected List<FullNamedExpression> type_bases;
514 TypeDefinition InTransit;
516 public TypeBuilder TypeBuilder;
517 GenericTypeParameterBuilder[] all_tp_builders;
519 // All recursive type parameters put together sharing same
520 // TypeParameter instances
522 TypeParameters all_type_parameters;
524 public const string DefaultIndexerName = "Item";
526 bool has_normal_indexers;
528 protected bool requires_delayed_unmanagedtype_check;
530 bool members_defined;
531 bool members_defined_ok;
532 protected bool has_static_constructor;
534 private CachedMethods cached_method;
536 protected TypeSpec spec;
537 TypeSpec current_type;
539 public int DynamicSitesCounter;
540 public int AnonymousMethodsCounter;
542 static readonly string[] attribute_targets = new string[] { "type" };
545 /// The pending methods that need to be implemented
546 // (interfaces or abstract methods)
548 PendingImplementation pending;
550 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
551 : base (parent, name, attrs, kind)
553 PartialContainer = this;
554 members = new List<MemberCore> ();
559 public List<FullNamedExpression> BaseTypeExpressions {
565 public override TypeSpec CurrentType {
567 if (current_type == null) {
568 if (IsGenericOrParentIsGeneric) {
570 // Switch to inflated version as it's used by all expressions
572 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
573 current_type = spec.MakeGenericType (this, targs);
583 public override TypeParameters CurrentTypeParameters {
585 return PartialContainer.MemberName.TypeParameters;
589 int CurrentTypeParametersStartIndex {
591 int total = all_tp_builders.Length;
592 if (CurrentTypeParameters != null) {
593 return total - CurrentTypeParameters.Count;
599 public virtual AssemblyDefinition DeclaringAssembly {
601 return Module.DeclaringAssembly;
605 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
607 return Module.DeclaringAssembly;
611 public TypeSpec Definition {
617 public bool HasMembersDefined {
619 return members_defined;
623 public bool HasInstanceConstructor {
625 return (caching_flags & Flags.HasInstanceConstructor) != 0;
628 caching_flags |= Flags.HasInstanceConstructor;
632 // Indicated whether container has StructLayout attribute set Explicit
633 public bool HasExplicitLayout {
634 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
635 set { caching_flags |= Flags.HasExplicitLayout; }
638 public bool HasOperators {
640 return (caching_flags & Flags.HasUserOperators) != 0;
643 caching_flags |= Flags.HasUserOperators;
647 public bool HasStructLayout {
648 get { return (caching_flags & Flags.HasStructLayout) != 0; }
649 set { caching_flags |= Flags.HasStructLayout; }
652 public TypeSpec[] Interfaces {
658 public bool IsGenericOrParentIsGeneric {
660 return all_type_parameters != null;
664 public bool IsTopLevel {
666 return !(Parent is TypeDefinition);
670 public bool IsPartial {
672 return (ModFlags & Modifiers.PARTIAL) != 0;
677 // Returns true for secondary partial containers
681 return PartialContainer != this;
685 public MemberCache MemberCache {
687 return spec.MemberCache;
691 public List<MemberCore> Members {
697 string ITypeDefinition.Namespace {
700 while (p.Kind != MemberKind.Namespace)
703 return p.MemberName == null ? null : p.GetSignatureForError ();
707 public TypeParameters TypeParametersAll {
709 return all_type_parameters;
713 public override string[] ValidAttributeTargets {
715 return attribute_targets;
721 public override void Accept (StructuralVisitor visitor)
723 visitor.Visit (this);
726 public void AddMember (MemberCore symbol)
728 if (symbol.MemberName.ExplicitInterface != null) {
729 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
730 Report.Error (541, symbol.Location,
731 "`{0}': explicit interface declaration can only be declared in a class or struct",
732 symbol.GetSignatureForError ());
736 AddNameToContainer (symbol, symbol.MemberName.Basename);
737 members.Add (symbol);
740 public override void AddTypeContainer (TypeContainer tc)
742 AddNameToContainer (tc, tc.Basename);
744 if (containers == null)
745 containers = new List<TypeContainer> ();
748 base.AddTypeContainer (tc);
751 public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
755 if (containers == null)
756 containers = new List<TypeContainer> ();
758 base.AddCompilerGeneratedClass (c);
762 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
764 public virtual void AddNameToContainer (MemberCore symbol, string name)
766 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
770 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
771 PartialContainer.defined_names.Add (name, symbol);
775 if (symbol.EnableOverloadChecks (mc))
778 InterfaceMemberBase im = mc as InterfaceMemberBase;
779 if (im != null && im.IsExplicitImpl)
782 Report.SymbolRelatedToPreviousError (mc);
783 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
784 Error_MissingPartialModifier (symbol);
788 if (symbol is TypeParameter) {
789 Report.Error (692, symbol.Location,
790 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
792 Report.Error (102, symbol.Location,
793 "The type `{0}' already contains a definition for `{1}'",
794 GetSignatureForError (), name);
800 public void AddConstructor (Constructor c)
802 AddConstructor (c, false);
805 public void AddConstructor (Constructor c, bool isDefault)
807 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
809 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
811 if (is_static && c.ParameterInfo.IsEmpty) {
812 PartialContainer.has_static_constructor = true;
814 PartialContainer.HasInstanceConstructor = true;
820 public bool AddField (FieldBase field)
824 if ((field.ModFlags & Modifiers.STATIC) != 0)
827 var first_field = PartialContainer.first_nonstatic_field;
828 if (first_field == null) {
829 PartialContainer.first_nonstatic_field = field;
833 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
834 Report.SymbolRelatedToPreviousError (first_field.Parent);
835 Report.Warning (282, 3, field.Location,
836 "struct instance field `{0}' found in different declaration from instance field `{1}'",
837 field.GetSignatureForError (), first_field.GetSignatureForError ());
843 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
845 public void AddIndexer (Indexer i)
850 public void AddOperator (Operator op)
852 PartialContainer.HasOperators = true;
856 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
858 if (has_normal_indexers && a.Type == pa.DefaultMember) {
859 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
863 if (a.Type == pa.Required) {
864 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
868 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
871 public override AttributeTargets AttributeTargets {
873 throw new NotSupportedException ();
877 public TypeSpec BaseType {
879 return spec.BaseType;
883 protected virtual TypeAttributes TypeAttr {
885 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
889 public int TypeParametersCount {
891 return MemberName.Arity;
895 TypeParameterSpec[] ITypeDefinition.TypeParameters {
897 return PartialContainer.CurrentTypeParameters.Types;
901 public string GetAttributeDefaultMember ()
903 return indexer_name ?? DefaultIndexerName;
906 public bool IsComImport {
908 if (OptAttributes == null)
911 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
915 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
918 PartialContainer.RegisterFieldForInitialization (field, expression);
920 if ((field.ModFlags & Modifiers.STATIC) != 0){
921 if (initialized_static_fields == null) {
922 HasStaticFieldInitializer = true;
923 initialized_static_fields = new List<FieldInitializer> (4);
926 initialized_static_fields.Add (expression);
928 if (initialized_fields == null)
929 initialized_fields = new List<FieldInitializer> (4);
931 initialized_fields.Add (expression);
935 public void ResolveFieldInitializers (BlockContext ec)
937 Debug.Assert (!IsPartialPart);
940 if (initialized_static_fields == null)
943 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
945 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
946 for (i = 0; i < initialized_static_fields.Count; ++i) {
947 FieldInitializer fi = initialized_static_fields [i];
948 ExpressionStatement s = fi.ResolveStatement (ec);
950 s = EmptyExpressionStatement.Instance;
951 } else if (!fi.IsSideEffectFree) {
952 has_complex_initializer |= true;
958 for (i = 0; i < initialized_static_fields.Count; ++i) {
959 FieldInitializer fi = initialized_static_fields [i];
961 // Need special check to not optimize code like this
962 // static int a = b = 5;
965 if (!has_complex_initializer && fi.IsDefaultInitializer)
968 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
974 if (initialized_fields == null)
977 for (int i = 0; i < initialized_fields.Count; ++i) {
978 FieldInitializer fi = initialized_fields [i];
979 ExpressionStatement s = fi.ResolveStatement (ec);
984 // Field is re-initialized to its default value => removed
986 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
989 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
993 public override string DocComment {
1005 public PendingImplementation PendingImplementations {
1006 get { return pending; }
1009 internal override void GenerateDocComment (DocumentationBuilder builder)
1014 base.GenerateDocComment (builder);
1016 foreach (var member in members)
1017 member.GenerateDocComment (builder);
1020 public TypeSpec GetAttributeCoClass ()
1022 if (OptAttributes == null)
1025 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1029 return a.GetCoClassAttributeValue ();
1032 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1035 if (OptAttributes != null) {
1036 a = OptAttributes.Search (pa);
1042 return a.GetAttributeUsageAttribute ();
1045 public virtual CompilationSourceFile GetCompilationSourceFile ()
1047 TypeContainer ns = Parent;
1049 var sf = ns as CompilationSourceFile;
1057 public virtual void AddBasesForPart (List<FullNamedExpression> bases)
1063 /// This function computes the Base class and also the
1064 /// list of interfaces that the class or struct @c implements.
1066 /// The return value is an array (might be null) of
1067 /// interfaces implemented (as Types).
1069 /// The @base_class argument is set to the base object or null
1070 /// if this is `System.Object'.
1072 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1075 if (type_bases == null)
1078 int count = type_bases.Count;
1079 TypeSpec[] ifaces = null;
1080 var base_context = new BaseContext (this);
1081 for (int i = 0, j = 0; i < count; i++){
1082 FullNamedExpression fne = type_bases [i];
1084 var fne_resolved = fne.ResolveAsType (base_context);
1085 if (fne_resolved == null)
1088 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1089 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1090 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1091 GetSignatureForError ());
1096 base_type = fne_resolved;
1102 ifaces = new TypeSpec [count - i];
1104 if (fne_resolved.IsInterface) {
1105 for (int ii = 0; ii < j; ++ii) {
1106 if (fne_resolved == ifaces [ii]) {
1107 Report.Error (528, Location, "`{0}' is already listed in interface list",
1108 fne_resolved.GetSignatureForError ());
1113 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1114 Report.Error (61, fne.Location,
1115 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1116 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1119 Report.SymbolRelatedToPreviousError (fne_resolved);
1120 if (Kind != MemberKind.Class) {
1121 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1122 } else if (base_class != null)
1123 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1124 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1126 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1127 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1131 ifaces [j++] = fne_resolved;
1138 // Checks that some operators come in pairs:
1144 // They are matched based on the return type and the argument types
1146 void CheckPairedOperators ()
1148 bool has_equality_or_inequality = false;
1149 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1151 for (int i = 0; i < members.Count; ++i) {
1152 var o_a = members[i] as Operator;
1156 var o_type = o_a.OperatorType;
1157 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1158 has_equality_or_inequality = true;
1160 if (found_matched.Contains (o_type))
1163 var matching_type = o_a.GetMatchingOperator ();
1164 if (matching_type == Operator.OpType.TOP) {
1168 bool pair_found = false;
1169 for (int ii = i + 1; ii < members.Count; ++ii) {
1170 var o_b = members[ii] as Operator;
1171 if (o_b == null || o_b.OperatorType != matching_type)
1174 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1177 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1180 found_matched.Add (matching_type);
1186 Report.Error (216, o_a.Location,
1187 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1188 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1192 if (has_equality_or_inequality) {
1194 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1195 GetSignatureForError ());
1197 if (!HasGetHashCode)
1198 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1199 GetSignatureForError ());
1203 public override void CreateMetadataName (StringBuilder sb)
1205 if (Parent.MemberName != null) {
1206 Parent.CreateMetadataName (sb);
1208 if (sb.Length != 0) {
1213 sb.Append (MemberName.Basename);
1216 bool CreateTypeBuilder ()
1219 // Sets .size to 1 for structs with no instance fields
1221 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
1223 var parent_def = Parent as TypeDefinition;
1224 if (parent_def == null) {
1225 var sb = new StringBuilder ();
1226 CreateMetadataName (sb);
1227 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1229 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1232 if (DeclaringAssembly.Importer != null)
1233 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1235 spec.SetMetaInfo (TypeBuilder);
1236 spec.MemberCache = new MemberCache (this);
1238 TypeParameters parentAllTypeParameters = null;
1239 if (parent_def != null) {
1240 spec.DeclaringType = Parent.CurrentType;
1241 parent_def.MemberCache.AddMember (spec);
1242 parentAllTypeParameters = parent_def.all_type_parameters;
1245 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1246 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1248 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1250 if (CurrentTypeParameters != null)
1251 CurrentTypeParameters.Define (all_tp_builders, spec, CurrentTypeParametersStartIndex, this);
1257 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1260 int parent_offset = 0;
1261 if (parentAllTypeParameters != null) {
1262 if (CurrentTypeParameters == null) {
1263 all_type_parameters = parentAllTypeParameters;
1264 return parentAllTypeParameters.GetAllNames ();
1267 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1268 all_type_parameters = new TypeParameters (names.Length);
1269 all_type_parameters.Add (parentAllTypeParameters);
1271 parent_offset = all_type_parameters.Count;
1272 for (int i = 0; i < parent_offset; ++i)
1273 names[i] = all_type_parameters[i].MemberName.Name;
1276 names = new string[CurrentTypeParameters.Count];
1279 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1280 if (all_type_parameters != null)
1281 all_type_parameters.Add (MemberName.TypeParameters[i]);
1283 var name = CurrentTypeParameters[i].MemberName.Name;
1284 names[parent_offset + i] = name;
1285 for (int ii = 0; ii < parent_offset + i; ++ii) {
1286 if (names[ii] != name)
1289 var tp = CurrentTypeParameters[i];
1290 var conflict = all_type_parameters[ii];
1292 tp.WarningParentNameConflict (conflict);
1296 if (all_type_parameters == null)
1297 all_type_parameters = CurrentTypeParameters;
1303 public SourceMethodBuilder CreateMethodSymbolEntry ()
1305 if (Module.DeclaringAssembly.SymbolWriter == null)
1308 var source_file = GetCompilationSourceFile ();
1309 if (source_file == null)
1312 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1316 // Creates a proxy base method call inside this container for hoisted base member calls
1318 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1320 Method proxy_method;
1323 // One proxy per base method is enough
1325 if (hoisted_base_call_proxies == null) {
1326 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1327 proxy_method = null;
1329 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1332 if (proxy_method == null) {
1333 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1334 var base_parameters = new Parameter[method.Parameters.Count];
1335 for (int i = 0; i < base_parameters.Length; ++i) {
1336 var base_param = method.Parameters.FixedParameters[i];
1337 base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
1338 base_param.Name, base_param.ModFlags, null, Location);
1339 base_parameters[i].Resolve (this, i);
1342 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1343 if (method.Parameters.HasArglist) {
1344 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1345 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1348 MemberName member_name;
1349 TypeArguments targs = null;
1350 if (method.IsGeneric) {
1352 // Copy all base generic method type parameters info
1354 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1355 var tparams = new TypeParameters ();
1357 targs = new TypeArguments ();
1358 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1359 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1360 var tp = hoisted_tparams[i];
1361 tparams.Add (new TypeParameter (tp, null, new MemberName (tp.Name, Location), null));
1363 targs.Add (new SimpleName (tp.Name, Location));
1364 targs.Arguments[i] = tp;
1367 member_name = new MemberName (name, tparams, Location);
1369 member_name = new MemberName (name);
1372 // Compiler generated proxy
1373 proxy_method = new Method (this, new TypeExpression (method.ReturnType, Location),
1374 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1375 member_name, cloned_params, null);
1377 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1378 IsCompilerGenerated = true
1381 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1382 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1384 mg.SetTypeArguments (rc, targs);
1386 // Get all the method parameters and pass them as arguments
1387 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1388 Statement statement;
1389 if (method.ReturnType.Kind == MemberKind.Void)
1390 statement = new StatementExpression (real_base_call);
1392 statement = new Return (real_base_call, Location);
1394 block.AddStatement (statement);
1395 proxy_method.Block = block;
1397 members.Add (proxy_method);
1398 proxy_method.Define ();
1400 hoisted_base_call_proxies.Add (method, proxy_method);
1403 return proxy_method.Spec;
1406 protected bool DefineBaseTypes ()
1408 iface_exprs = ResolveBaseTypes (out base_type_expr);
1411 if (IsPartialPart) {
1412 set_base_type = false;
1414 if (base_type_expr != null) {
1415 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1416 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1417 Report.Error (263, Location,
1418 "Partial declarations of `{0}' must not specify different base classes",
1419 GetSignatureForError ());
1421 PartialContainer.base_type_expr = base_type_expr;
1422 PartialContainer.base_type = base_type;
1423 set_base_type = true;
1427 if (iface_exprs != null) {
1428 if (PartialContainer.iface_exprs == null)
1429 PartialContainer.iface_exprs = iface_exprs;
1431 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1432 foreach (var iface_partial in iface_exprs) {
1433 if (ifaces.Contains (iface_partial))
1436 ifaces.Add (iface_partial);
1439 PartialContainer.iface_exprs = ifaces.ToArray ();
1443 PartialContainer.members.AddRange (members);
1444 if (containers != null) {
1445 if (PartialContainer.containers == null)
1446 PartialContainer.containers = new List<TypeContainer> ();
1448 PartialContainer.containers.AddRange (containers);
1451 members_defined = members_defined_ok = true;
1452 caching_flags |= Flags.CloseTypeCreated;
1454 set_base_type = true;
1457 var cycle = CheckRecursiveDefinition (this);
1458 if (cycle != null) {
1459 Report.SymbolRelatedToPreviousError (cycle);
1460 if (this is Interface) {
1461 Report.Error (529, Location,
1462 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1463 GetSignatureForError (), cycle.GetSignatureForError ());
1467 Report.Error (146, Location,
1468 "Circular base class dependency involving `{0}' and `{1}'",
1469 GetSignatureForError (), cycle.GetSignatureForError ());
1475 if (iface_exprs != null) {
1476 foreach (var iface_type in iface_exprs) {
1477 // Prevents a crash, the interface might not have been resolved: 442144
1478 if (iface_type == null)
1481 if (!spec.AddInterfaceDefined (iface_type))
1484 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1486 // Ensure the base is always setup
1487 var compiled_iface = iface_type.MemberDefinition as Interface;
1488 if (compiled_iface != null) {
1489 // TODO: Need DefineBaseType only
1490 compiled_iface.DefineContainer ();
1493 if (iface_type.Interfaces != null) {
1494 var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
1495 for (int i = 0; i < base_ifaces.Count; ++i) {
1496 var ii_iface_type = base_ifaces[i];
1497 if (spec.AddInterfaceDefined (ii_iface_type)) {
1498 TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
1500 if (ii_iface_type.Interfaces != null)
1501 base_ifaces.AddRange (ii_iface_type.Interfaces);
1508 if (Kind == MemberKind.Interface) {
1509 spec.BaseType = Compiler.BuiltinTypes.Object;
1513 if (set_base_type) {
1514 if (base_type != null) {
1515 spec.BaseType = base_type;
1517 // Set base type after type creation
1518 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1520 TypeBuilder.SetParent (null);
1527 public override void PrepareEmit ()
1529 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1532 foreach (var member in members) {
1533 var pm = member as IParametersMember;
1536 var p = pm.Parameters;
1540 ((ParametersCompiled) p).ResolveDefaultValues (member);
1543 var c = member as Const;
1548 base.PrepareEmit ();
1552 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1554 public override bool CreateContainer ()
1556 if (TypeBuilder != null)
1562 if (IsPartialPart) {
1563 spec = PartialContainer.spec;
1564 TypeBuilder = PartialContainer.TypeBuilder;
1565 all_tp_builders = PartialContainer.all_tp_builders;
1566 all_type_parameters = PartialContainer.all_type_parameters;
1568 if (!CreateTypeBuilder ()) {
1574 return base.CreateContainer ();
1577 protected override void DoDefineContainer ()
1581 DoResolveTypeParameters ();
1585 // Replaces normal spec with predefined one when compiling corlib
1586 // and this type container defines predefined type
1588 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1590 // When compiling build-in types we start with two
1591 // version of same type. One is of BuiltinTypeSpec and
1592 // second one is ordinary TypeSpec. The unification
1593 // happens at later stage when we know which type
1594 // really matches the builtin type signature. However
1595 // that means TypeSpec create during CreateType of this
1596 // type has to be replaced with builtin one
1598 spec.SetMetaInfo (TypeBuilder);
1599 spec.MemberCache = this.spec.MemberCache;
1600 spec.DeclaringType = this.spec.DeclaringType;
1603 current_type = null;
1606 void UpdateTypeParameterConstraints (TypeDefinition part)
1608 for (int i = 0; i < CurrentTypeParameters.Count; i++) {
1609 if (CurrentTypeParameters[i].AddPartialConstraints (part, part.MemberName.TypeParameters[i]))
1612 Report.SymbolRelatedToPreviousError (Location, "");
1613 Report.Error (265, part.Location,
1614 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1615 GetSignatureForError (), CurrentTypeParameters[i].GetSignatureForError ());
1619 public override void RemoveContainer (TypeContainer cont)
1621 base.RemoveContainer (cont);
1622 Members.Remove (cont);
1623 Cache.Remove (cont.Basename);
1626 protected virtual bool DoResolveTypeParameters ()
1628 var tparams = CurrentTypeParameters;
1629 if (tparams == null)
1632 var base_context = new BaseContext (this);
1633 for (int i = 0; i < tparams.Count; ++i) {
1634 var tp = tparams[i];
1636 if (!tp.ResolveConstraints (base_context)) {
1642 if (IsPartialPart) {
1643 PartialContainer.UpdateTypeParameterConstraints (this);
1649 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1651 if (InTransit != null)
1656 if (base_type != null) {
1657 var ptc = base_type.MemberDefinition as TypeDefinition;
1658 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1662 if (iface_exprs != null) {
1663 foreach (var iface in iface_exprs) {
1664 // the interface might not have been resolved, prevents a crash, see #442144
1667 var ptc = iface.MemberDefinition as Interface;
1668 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1673 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1681 /// Populates our TypeBuilder with fields and methods
1683 public sealed override bool Define ()
1685 if (members_defined)
1686 return members_defined_ok;
1688 members_defined_ok = DoDefineMembers ();
1689 members_defined = true;
1693 return members_defined_ok;
1696 protected virtual bool DoDefineMembers ()
1698 Debug.Assert (!IsPartialPart);
1700 if (iface_exprs != null) {
1701 foreach (var iface_type in iface_exprs) {
1702 if (iface_type == null)
1705 // Ensure the base is always setup
1706 var compiled_iface = iface_type.MemberDefinition as Interface;
1707 if (compiled_iface != null)
1708 compiled_iface.Define ();
1710 if (Kind == MemberKind.Interface)
1711 MemberCache.AddInterface (iface_type);
1713 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1714 if (oa != null && !IsObsolete)
1715 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1717 if (iface_type.Arity > 0) {
1718 // TODO: passing `this' is wrong, should be base type iface instead
1719 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1721 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1722 Report.Error (1966, Location,
1723 "`{0}': cannot implement a dynamic interface `{1}'",
1724 GetSignatureForError (), iface_type.GetSignatureForError ());
1729 if (iface_type.IsGenericOrParentIsGeneric) {
1730 if (spec.Interfaces != null) {
1731 foreach (var prev_iface in iface_exprs) {
1732 if (prev_iface == iface_type)
1735 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1738 Report.Error (695, Location,
1739 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1740 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1747 if (base_type != null) {
1749 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1751 if (base_type_expr != null) {
1752 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1753 if (obsolete_attr != null && !IsObsolete)
1754 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1756 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1757 Report.Error (698, base_type_expr.Location,
1758 "A generic type cannot derive from `{0}' because it is an attribute class",
1759 base_type.GetSignatureForError ());
1763 if (base_type.Interfaces != null) {
1764 foreach (var iface in base_type.Interfaces)
1765 spec.AddInterface (iface);
1768 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1769 if (baseContainer != null) {
1770 baseContainer.Define ();
1773 // It can trigger define of this type (for generic types only)
1775 if (HasMembersDefined)
1780 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1781 pending = PendingImplementation.GetPendingImplementations (this);
1784 var count = members.Count;
1785 for (int i = 0; i < count; ++i) {
1786 var mc = members[i] as InterfaceMemberBase;
1787 if (mc == null || !mc.IsExplicitImpl)
1792 } catch (Exception e) {
1793 throw new InternalErrorException (mc, e);
1797 for (int i = 0; i < count; ++i) {
1798 var mc = members[i] as InterfaceMemberBase;
1799 if (mc != null && mc.IsExplicitImpl)
1802 if (members[i] is TypeContainer)
1806 members[i].Define ();
1807 } catch (Exception e) {
1808 throw new InternalErrorException (members[i], e);
1813 CheckPairedOperators ();
1816 if (requires_delayed_unmanagedtype_check) {
1817 requires_delayed_unmanagedtype_check = false;
1818 foreach (var member in members) {
1819 var f = member as Field;
1820 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1821 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1825 ComputeIndexerName();
1827 if (HasEquals && !HasGetHashCode) {
1828 Report.Warning (659, 3, Location,
1829 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1832 if (Kind == MemberKind.Interface && iface_exprs != null) {
1833 MemberCache.RemoveHiddenMembers (spec);
1839 void ComputeIndexerName ()
1841 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1842 if (indexers == null)
1845 string class_indexer_name = null;
1848 // Check normal indexers for consistent name, explicit interface implementation
1849 // indexers are ignored
1851 foreach (var indexer in indexers) {
1853 // FindMembers can return unfiltered full hierarchy names
1855 if (indexer.DeclaringType != spec)
1858 has_normal_indexers = true;
1860 if (class_indexer_name == null) {
1861 indexer_name = class_indexer_name = indexer.Name;
1865 if (indexer.Name != class_indexer_name)
1866 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1867 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1871 void EmitIndexerName ()
1873 if (!has_normal_indexers)
1876 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1880 var encoder = new AttributeEncoder ();
1881 encoder.Encode (GetAttributeDefaultMember ());
1882 encoder.EncodeEmptyNamedArguments ();
1884 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1887 public override void VerifyMembers ()
1890 // Check for internal or private fields that were never assigned
1892 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1893 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1894 foreach (var member in members) {
1895 if (member is Event) {
1897 // An event can be assigned from same class only, so we can report
1898 // this warning for all accessibility modes
1901 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1906 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1907 if (is_type_exposed)
1910 member.SetIsUsed ();
1913 var f = member as Field;
1917 if (!member.IsUsed) {
1918 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1919 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1921 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1922 member.GetSignatureForError ());
1927 if ((f.caching_flags & Flags.IsAssigned) != 0)
1931 // Only report 649 on level 4
1933 if (Compiler.Settings.WarningLevel < 4)
1937 // Don't be pedantic when type requires specific layout
1939 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1942 Constant c = New.Constantify (f.MemberType, f.Location);
1945 value = c.GetValueAsLiteral ();
1946 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
1953 value = " `" + value + "'";
1955 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
1956 f.GetSignatureForError (), value);
1960 base.VerifyMembers ();
1963 public override void Emit ()
1965 if (OptAttributes != null)
1966 OptAttributes.Emit ();
1968 if (!IsCompilerGenerated) {
1970 MemberSpec candidate;
1971 bool overrides = false;
1972 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
1973 if (conflict_symbol == null && candidate == null) {
1974 if ((ModFlags & Modifiers.NEW) != 0)
1975 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1976 GetSignatureForError ());
1978 if ((ModFlags & Modifiers.NEW) == 0) {
1979 if (candidate == null)
1980 candidate = conflict_symbol;
1982 Report.SymbolRelatedToPreviousError (candidate);
1983 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1984 GetSignatureForError (), candidate.GetSignatureForError ());
1989 // Run constraints check on all possible generic types
1990 if (base_type != null && base_type_expr != null) {
1991 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
1994 if (iface_exprs != null) {
1995 foreach (var iface_type in iface_exprs) {
1996 if (iface_type == null)
1999 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2004 if (all_tp_builders != null) {
2005 int current_starts_index = CurrentTypeParametersStartIndex;
2006 for (int i = 0; i < all_tp_builders.Length; i++) {
2007 if (i < current_starts_index) {
2008 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2010 var tp = CurrentTypeParameters [i - current_starts_index];
2011 tp.CheckGenericConstraints (!IsObsolete);
2017 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2018 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2021 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2022 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2027 for (int i = 0; i < members.Count; i++)
2031 CheckAttributeClsCompliance ();
2033 if (pending != null)
2034 pending.VerifyPendingMethods ();
2038 void CheckAttributeClsCompliance ()
2040 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2043 foreach (var m in members) {
2044 var c = m as Constructor;
2048 if (c.HasCompliantArgs)
2052 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2055 public sealed override void EmitContainer ()
2057 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2063 public override void CloseContainer ()
2065 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2068 // Close base type container first to avoid TypeLoadException
2069 if (spec.BaseType != null) {
2070 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2071 if (btype != null) {
2072 btype.CloseContainer ();
2074 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2080 caching_flags |= Flags.CloseTypeCreated;
2081 TypeBuilder.CreateType ();
2082 } catch (TypeLoadException) {
2084 // This is fine, the code still created the type
2086 } catch (Exception e) {
2087 throw new InternalErrorException (this, e);
2090 base.CloseContainer ();
2093 initialized_fields = null;
2094 initialized_static_fields = null;
2096 OptAttributes = null;
2100 // Performs the validation on a Method's modifiers (properties have
2101 // the same properties).
2103 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2105 public bool MethodModifiersValid (MemberCore mc)
2107 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2108 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2110 var flags = mc.ModFlags;
2113 // At most one of static, virtual or override
2115 if ((flags & Modifiers.STATIC) != 0){
2116 if ((flags & vao) != 0){
2117 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2118 mc.GetSignatureForError ());
2123 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2124 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2125 mc.GetSignatureForError ());
2130 // If the declaration includes the abstract modifier, then the
2131 // declaration does not include static, virtual or extern
2133 if ((flags & Modifiers.ABSTRACT) != 0){
2134 if ((flags & Modifiers.EXTERN) != 0){
2136 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2140 if ((flags & Modifiers.SEALED) != 0) {
2141 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2145 if ((flags & Modifiers.VIRTUAL) != 0){
2146 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2150 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2151 Report.SymbolRelatedToPreviousError (this);
2152 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2153 mc.GetSignatureForError (), GetSignatureForError ());
2158 if ((flags & Modifiers.PRIVATE) != 0){
2159 if ((flags & vao) != 0){
2160 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2165 if ((flags & Modifiers.SEALED) != 0){
2166 if ((flags & Modifiers.OVERRIDE) == 0){
2167 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2175 protected override bool VerifyClsCompliance ()
2177 if (!base.VerifyClsCompliance ())
2180 // Check all container names for user classes
2181 if (Kind != MemberKind.Delegate)
2182 MemberCache.VerifyClsCompliance (Definition, Report);
2184 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2185 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2186 GetSignatureForError (), BaseType.GetSignatureForError ());
2192 /// Performs checks for an explicit interface implementation. First it
2193 /// checks whether the `interface_type' is a base inteface implementation.
2194 /// Then it checks whether `name' exists in the interface type.
2196 public bool VerifyImplements (InterfaceMemberBase mb)
2198 var ifaces = spec.Interfaces;
2199 if (ifaces != null) {
2200 foreach (TypeSpec t in ifaces){
2201 if (t == mb.InterfaceType)
2206 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2207 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2208 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2213 // Used for visiblity checks to tests whether this definition shares
2214 // base type baseType, it does member-definition search
2216 public bool IsBaseTypeDefinition (TypeSpec baseType)
2218 // RootContext check
2219 if (TypeBuilder == null)
2224 if (type.MemberDefinition == baseType.MemberDefinition)
2227 type = type.BaseType;
2228 } while (type != null);
2233 public override bool IsClsComplianceRequired ()
2236 return PartialContainer.IsClsComplianceRequired ();
2238 return base.IsClsComplianceRequired ();
2241 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2243 return Module.DeclaringAssembly == assembly;
2246 public virtual bool IsUnmanagedType ()
2251 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2253 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2257 // Public function used to locate types.
2259 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2261 // Returns: Type or null if they type can not be found.
2263 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2265 FullNamedExpression e;
2266 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2272 var tp = CurrentTypeParameters;
2274 TypeParameter tparam = tp.Find (name);
2276 e = new TypeParameterExpr (tparam, Location.Null);
2281 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2283 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2284 e = new TypeExpression (t, Location.Null);
2286 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2290 // TODO MemberCache: How to cache arity stuff ?
2291 if (arity == 0 && mode == LookupMode.Normal)
2297 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2299 // Has any nested type
2300 // Does not work, because base type can have
2301 //if (PartialContainer.Types == null)
2304 var container = PartialContainer.CurrentType;
2305 return MemberCache.FindNestedType (container, name, arity);
2308 public void Mark_HasEquals ()
2310 cached_method |= CachedMethods.Equals;
2313 public void Mark_HasGetHashCode ()
2315 cached_method |= CachedMethods.GetHashCode;
2318 public override void WriteDebugSymbol (MonoSymbolFile file)
2323 foreach (var m in members) {
2324 m.WriteDebugSymbol (file);
2329 /// Method container contains Equals method
2331 public bool HasEquals {
2333 return (cached_method & CachedMethods.Equals) != 0;
2338 /// Method container contains GetHashCode method
2340 public bool HasGetHashCode {
2342 return (cached_method & CachedMethods.GetHashCode) != 0;
2346 public bool HasStaticFieldInitializer {
2348 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2352 cached_method |= CachedMethods.HasStaticFieldInitializer;
2354 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2358 public override string DocCommentHeader {
2359 get { return "T:"; }
2363 public abstract class ClassOrStruct : TypeDefinition
2365 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2367 SecurityType declarative_security;
2369 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2370 : base (parent, name, attrs, kind)
2374 protected override TypeAttributes TypeAttr {
2376 TypeAttributes ta = base.TypeAttr;
2377 if (!has_static_constructor)
2378 ta |= TypeAttributes.BeforeFieldInit;
2380 if (Kind == MemberKind.Class) {
2381 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2383 ta |= StaticClassAttribute;
2385 ta |= TypeAttributes.SequentialLayout;
2392 public override void AddNameToContainer (MemberCore symbol, string name)
2394 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2395 if (symbol is TypeParameter) {
2396 Report.Error (694, symbol.Location,
2397 "Type parameter `{0}' has same name as containing type, or method",
2398 symbol.GetSignatureForError ());
2402 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2403 if (imb == null || !imb.IsExplicitImpl) {
2404 Report.SymbolRelatedToPreviousError (this);
2405 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2406 symbol.GetSignatureForError ());
2411 base.AddNameToContainer (symbol, name);
2414 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2416 if (a.IsValidSecurityAttribute ()) {
2417 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2421 if (a.Type == pa.StructLayout) {
2422 PartialContainer.HasStructLayout = true;
2423 if (a.IsExplicitLayoutKind ())
2424 PartialContainer.HasExplicitLayout = true;
2427 if (a.Type == pa.Dynamic) {
2428 a.Error_MisusedDynamicAttribute ();
2432 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2436 /// Defines the default constructors
2438 protected Constructor DefineDefaultConstructor (bool is_static)
2440 // The default instance constructor is public
2441 // If the class is abstract, the default constructor is protected
2442 // The default static constructor is private
2446 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2448 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2451 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2452 c.Initializer = new GeneratedBaseInitializer (Location);
2454 AddConstructor (c, true);
2455 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2456 IsCompilerGenerated = true
2462 protected override bool DoDefineMembers ()
2464 CheckProtectedModifier ();
2466 base.DoDefineMembers ();
2471 public override void Emit ()
2473 if (!has_static_constructor && HasStaticFieldInitializer) {
2474 var c = DefineDefaultConstructor (true);
2480 if (declarative_security != null) {
2481 foreach (var de in declarative_security) {
2483 TypeBuilder.__AddDeclarativeSecurity (de);
2485 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2493 public sealed class Class : ClassOrStruct
2495 const Modifiers AllowedModifiers =
2498 Modifiers.PROTECTED |
2499 Modifiers.INTERNAL |
2501 Modifiers.ABSTRACT |
2506 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2507 : base (parent, name, attrs, MemberKind.Class)
2509 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2510 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2511 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2514 public override void Accept (StructuralVisitor visitor)
2516 visitor.Visit (this);
2519 public override void AddBasesForPart (List<FullNamedExpression> bases)
2521 var pmn = MemberName;
2522 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2523 Report.Error (537, Location,
2524 "The class System.Object cannot have a base class or implement an interface.");
2526 base.AddBasesForPart (bases);
2529 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2531 if (a.Type == pa.AttributeUsage) {
2532 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2533 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2537 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2538 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2542 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2543 a.Error_MissingGuidAttribute ();
2547 if (a.Type == pa.Extension) {
2548 a.Error_MisusedExtensionAttribute ();
2552 if (a.Type.IsConditionallyExcluded (this, Location))
2555 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2558 public override AttributeTargets AttributeTargets {
2560 return AttributeTargets.Class;
2564 protected override bool DoDefineMembers ()
2566 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2567 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2570 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2571 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2575 foreach (var m in Members) {
2576 if (m is Operator) {
2577 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2581 if (m is Destructor) {
2582 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2587 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2591 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2594 if (m is Constructor) {
2595 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2599 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2602 if (!PartialContainer.HasInstanceConstructor)
2603 DefineDefaultConstructor (false);
2606 return base.DoDefineMembers ();
2609 public override void Emit ()
2613 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2614 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2616 if (base_type != null && base_type.HasDynamicElement) {
2617 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2621 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2623 var ifaces = base.ResolveBaseTypes (out base_class);
2625 if (base_class == null) {
2626 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2627 base_type = Compiler.BuiltinTypes.Object;
2629 if (base_type.IsGenericParameter){
2630 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2631 GetSignatureForError (), base_type.GetSignatureForError ());
2632 } else if (base_type.IsStatic) {
2633 Report.SymbolRelatedToPreviousError (base_type);
2634 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2635 GetSignatureForError (), base_type.GetSignatureForError ());
2636 } else if (base_type.IsSealed) {
2637 Report.SymbolRelatedToPreviousError (base_type);
2638 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2639 GetSignatureForError (), base_type.GetSignatureForError ());
2640 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2641 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2642 GetSignatureForError (), base_type.GetSignatureForError ());
2645 switch (base_type.BuiltinType) {
2646 case BuiltinTypeSpec.Type.Enum:
2647 case BuiltinTypeSpec.Type.ValueType:
2648 case BuiltinTypeSpec.Type.MulticastDelegate:
2649 case BuiltinTypeSpec.Type.Delegate:
2650 case BuiltinTypeSpec.Type.Array:
2651 if (!(spec is BuiltinTypeSpec)) {
2652 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2653 GetSignatureForError (), base_type.GetSignatureForError ());
2655 base_type = Compiler.BuiltinTypes.Object;
2660 if (!IsAccessibleAs (base_type)) {
2661 Report.SymbolRelatedToPreviousError (base_type);
2662 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2663 base_type.GetSignatureForError (), GetSignatureForError ());
2667 if (PartialContainer.IsStatic && ifaces != null) {
2668 foreach (var t in ifaces)
2669 Report.SymbolRelatedToPreviousError (t);
2670 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2676 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2677 /// Valid only for attribute classes.
2678 public override string[] ConditionalConditions ()
2680 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2683 caching_flags &= ~Flags.Excluded_Undetected;
2685 if (OptAttributes == null)
2688 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2692 string[] conditions = new string[attrs.Length];
2693 for (int i = 0; i < conditions.Length; ++i)
2694 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2696 caching_flags |= Flags.Excluded;
2701 public sealed class Struct : ClassOrStruct
2703 bool is_unmanaged, has_unmanaged_check_done;
2707 // Modifiers allowed in a struct declaration
2709 const Modifiers AllowedModifiers =
2712 Modifiers.PROTECTED |
2713 Modifiers.INTERNAL |
2717 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2718 : base (parent, name, attrs, MemberKind.Struct)
2720 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2721 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2722 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2725 public override AttributeTargets AttributeTargets {
2727 return AttributeTargets.Struct;
2731 public override void Accept (StructuralVisitor visitor)
2733 visitor.Visit (this);
2736 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2738 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2741 // When struct constains fixed fixed and struct layout has explicitly
2742 // set CharSet, its value has to be propagated to compiler generated
2745 if (a.Type == pa.StructLayout) {
2746 var value = a.GetNamedValue ("CharSet");
2750 for (int i = 0; i < Members.Count; ++i) {
2751 FixedField ff = Members [i] as FixedField;
2755 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2760 bool CheckStructCycles ()
2766 foreach (var member in Members) {
2767 var field = member as Field;
2771 TypeSpec ftype = field.Spec.MemberType;
2772 if (!ftype.IsStruct)
2775 if (ftype is BuiltinTypeSpec)
2778 foreach (var targ in ftype.TypeArguments) {
2779 if (!CheckFieldTypeCycle (targ)) {
2780 Report.Error (523, field.Location,
2781 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2782 field.GetSignatureForError (), ftype.GetSignatureForError ());
2788 // Static fields of exactly same type are allowed
2790 if (field.IsStatic && ftype == CurrentType)
2793 if (!CheckFieldTypeCycle (ftype)) {
2794 Report.Error (523, field.Location,
2795 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2796 field.GetSignatureForError (), ftype.GetSignatureForError ());
2805 static bool CheckFieldTypeCycle (TypeSpec ts)
2807 var fts = ts.MemberDefinition as Struct;
2811 return fts.CheckStructCycles ();
2814 public override void Emit ()
2816 CheckStructCycles ();
2821 public override bool IsUnmanagedType ()
2823 if (has_unmanaged_check_done)
2824 return is_unmanaged;
2826 if (requires_delayed_unmanagedtype_check)
2829 var parent_def = Parent.PartialContainer;
2830 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2831 has_unmanaged_check_done = true;
2835 if (first_nonstatic_field != null) {
2836 requires_delayed_unmanagedtype_check = true;
2838 foreach (var member in Members) {
2839 var f = member as Field;
2846 // It can happen when recursive unmanaged types are defined
2847 // struct S { S* s; }
2848 TypeSpec mt = f.MemberType;
2856 has_unmanaged_check_done = true;
2860 has_unmanaged_check_done = true;
2863 is_unmanaged = true;
2867 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2869 var ifaces = base.ResolveBaseTypes (out base_class);
2870 base_type = Compiler.BuiltinTypes.ValueType;
2874 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2876 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2877 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2878 field.GetSignatureForError ());
2881 base.RegisterFieldForInitialization (field, expression);
2889 public sealed class Interface : TypeDefinition {
2892 /// Modifiers allowed in a class declaration
2894 const Modifiers AllowedModifiers =
2897 Modifiers.PROTECTED |
2898 Modifiers.INTERNAL |
2902 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2903 : base (parent, name, attrs, MemberKind.Interface)
2905 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2907 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2908 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2913 public override AttributeTargets AttributeTargets {
2915 return AttributeTargets.Interface;
2919 protected override TypeAttributes TypeAttr {
2921 const TypeAttributes DefaultTypeAttributes =
2922 TypeAttributes.AutoLayout |
2923 TypeAttributes.Abstract |
2924 TypeAttributes.Interface;
2926 return base.TypeAttr | DefaultTypeAttributes;
2932 public override void Accept (StructuralVisitor visitor)
2934 visitor.Visit (this);
2937 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2939 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2940 a.Error_MissingGuidAttribute ();
2944 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2947 protected override bool VerifyClsCompliance ()
2949 if (!base.VerifyClsCompliance ())
2952 if (iface_exprs != null) {
2953 foreach (var iface in iface_exprs) {
2954 if (iface.IsCLSCompliant ())
2957 Report.SymbolRelatedToPreviousError (iface);
2958 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2959 GetSignatureForError (), TypeManager.CSharpName (iface));
2967 public abstract class InterfaceMemberBase : MemberBase
2970 // Common modifiers allowed in a class declaration
2972 protected const Modifiers AllowedModifiersClass =
2975 Modifiers.PROTECTED |
2976 Modifiers.INTERNAL |
2981 Modifiers.OVERRIDE |
2982 Modifiers.ABSTRACT |
2987 // Common modifiers allowed in a struct declaration
2989 protected const Modifiers AllowedModifiersStruct =
2992 Modifiers.PROTECTED |
2993 Modifiers.INTERNAL |
2996 Modifiers.OVERRIDE |
3001 // Common modifiers allowed in a interface declaration
3003 protected const Modifiers AllowedModifiersInterface =
3008 // Whether this is an interface member.
3010 public bool IsInterface;
3013 // If true, this is an explicit interface implementation
3015 public readonly bool IsExplicitImpl;
3017 protected bool is_external_implementation;
3020 // The interface type we are explicitly implementing
3022 public TypeSpec InterfaceType;
3025 // The method we're overriding if this is an override method.
3027 protected MethodSpec base_method;
3029 readonly Modifiers explicit_mod_flags;
3030 public MethodAttributes flags;
3032 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3033 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3035 IsInterface = parent.Kind == MemberKind.Interface;
3036 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3037 explicit_mod_flags = mod;
3040 public abstract Variance ExpectedMemberTypeVariance { get; }
3042 protected override bool CheckBase ()
3044 if (!base.CheckBase ())
3047 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3048 CheckForDuplications ();
3053 // For System.Object only
3054 if (Parent.BaseType == null)
3057 MemberSpec candidate;
3058 bool overrides = false;
3059 var base_member = FindBaseMember (out candidate, ref overrides);
3061 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3062 if (base_member == null) {
3063 if (candidate == null) {
3064 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3065 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3066 "object.Finalize()");
3068 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3069 GetSignatureForError (), SimpleName.GetMemberType (this));
3072 Report.SymbolRelatedToPreviousError (candidate);
3074 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3075 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3076 else if (this is PropertyBase)
3077 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3078 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3080 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3081 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3088 // Handles ambiguous overrides
3090 if (candidate != null) {
3091 Report.SymbolRelatedToPreviousError (candidate);
3092 Report.SymbolRelatedToPreviousError (base_member);
3094 // Get member definition for error reporting
3095 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3096 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3098 Report.Error (462, Location,
3099 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3100 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3103 if (!CheckOverrideAgainstBase (base_member))
3106 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3108 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3109 Report.SymbolRelatedToPreviousError (base_member);
3110 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3111 GetSignatureForError (), base_member.GetSignatureForError ());
3114 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3115 Report.SymbolRelatedToPreviousError (base_member);
3116 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3117 GetSignatureForError (), base_member.GetSignatureForError ());
3121 base_method = base_member as MethodSpec;
3125 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3126 base_member = candidate;
3128 if (base_member == null) {
3129 if ((ModFlags & Modifiers.NEW) != 0) {
3130 if (base_member == null) {
3131 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3132 GetSignatureForError ());
3136 if ((ModFlags & Modifiers.NEW) == 0) {
3137 ModFlags |= Modifiers.NEW;
3138 if (!IsCompilerGenerated) {
3139 Report.SymbolRelatedToPreviousError (base_member);
3140 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3141 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",
3142 GetSignatureForError (), base_member.GetSignatureForError ());
3144 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3145 GetSignatureForError (), base_member.GetSignatureForError ());
3150 if (!IsInterface && base_member.IsAbstract && !overrides) {
3151 Report.SymbolRelatedToPreviousError (base_member);
3152 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3153 GetSignatureForError (), base_member.GetSignatureForError ());
3160 protected virtual bool CheckForDuplications ()
3162 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3166 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3167 // that have been defined.
3169 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3173 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3174 Report.SymbolRelatedToPreviousError (base_member);
3175 Report.Error (506, Location,
3176 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3177 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3181 // Now we check that the overriden method is not final
3182 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3183 Report.SymbolRelatedToPreviousError (base_member);
3184 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3185 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3189 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3190 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3191 Report.SymbolRelatedToPreviousError (base_member);
3192 if (this is PropertyBasedMember) {
3193 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3194 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3196 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3197 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3205 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3207 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3208 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3210 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3212 // It must be at least "protected"
3214 if ((thisp & Modifiers.PROTECTED) == 0) {
3219 // when overriding protected internal, the method can be declared
3220 // protected internal only within the same assembly or assembly
3221 // which has InternalsVisibleTo
3223 if ((thisp & Modifiers.INTERNAL) != 0) {
3224 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3228 // protected overriding protected internal inside same assembly
3229 // requires internal modifier as well
3231 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3238 return thisp == base_classp;
3241 public override bool Define ()
3244 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3245 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3247 flags = MethodAttributes.Public |
3248 MethodAttributes.Abstract |
3249 MethodAttributes.HideBySig |
3250 MethodAttributes.NewSlot |
3251 MethodAttributes.Virtual;
3253 Parent.PartialContainer.MethodModifiersValid (this);
3255 flags = ModifiersExtensions.MethodAttr (ModFlags);
3258 if (IsExplicitImpl) {
3259 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3260 if (InterfaceType == null)
3263 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3264 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3265 GetSignatureForError ());
3268 if (!InterfaceType.IsInterface) {
3269 Report.SymbolRelatedToPreviousError (InterfaceType);
3270 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3271 TypeManager.CSharpName (InterfaceType));
3273 Parent.PartialContainer.VerifyImplements (this);
3276 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3279 return base.Define ();
3282 protected bool DefineParameters (ParametersCompiled parameters)
3284 if (!parameters.Resolve (this))
3288 for (int i = 0; i < parameters.Count; ++i) {
3289 Parameter p = parameters [i];
3291 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3292 p.Warning_UselessOptionalParameter (Report);
3294 if (p.CheckAccessibility (this))
3297 TypeSpec t = parameters.Types [i];
3298 Report.SymbolRelatedToPreviousError (t);
3299 if (this is Indexer)
3300 Report.Error (55, Location,
3301 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3302 TypeManager.CSharpName (t), GetSignatureForError ());
3303 else if (this is Operator)
3304 Report.Error (57, Location,
3305 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3306 TypeManager.CSharpName (t), GetSignatureForError ());
3308 Report.Error (51, Location,
3309 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3310 TypeManager.CSharpName (t), GetSignatureForError ());
3316 protected override void DoMemberTypeDependentChecks ()
3318 base.DoMemberTypeDependentChecks ();
3320 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3323 public override void Emit()
3325 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3326 // We are more strict than csc and report this as an error because SRE does not allow emit that
3327 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3328 if (this is Constructor) {
3329 Report.Warning (824, 1, Location,
3330 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3332 Report.Warning (626, 1, Location,
3333 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3334 GetSignatureForError ());
3341 public override bool EnableOverloadChecks (MemberCore overload)
3344 // Two members can differ in their explicit interface
3345 // type parameter only
3347 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3348 if (imb != null && imb.IsExplicitImpl) {
3349 if (IsExplicitImpl) {
3350 caching_flags |= Flags.MethodOverloadsExist;
3355 return IsExplicitImpl;
3358 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3360 var base_modifiers = base_member.Modifiers;
3362 // Remove internal modifier from types which are not internally accessible
3363 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3364 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3365 base_modifiers = Modifiers.PROTECTED;
3367 Report.SymbolRelatedToPreviousError (base_member);
3368 Report.Error (507, member.Location,
3369 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3370 member.GetSignatureForError (),
3371 ModifiersExtensions.AccessibilityName (base_modifiers),
3372 base_member.GetSignatureForError ());
3375 protected void Error_StaticReturnType ()
3377 Report.Error (722, Location,
3378 "`{0}': static types cannot be used as return types",
3379 MemberType.GetSignatureForError ());
3383 /// Gets base method and its return type
3385 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3387 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3391 // The "short" name of this property / indexer / event. This is the
3392 // name without the explicit interface.
3394 public string ShortName {
3395 get { return MemberName.Name; }
3399 // Returns full metadata method name
3401 public string GetFullName (MemberName name)
3403 return GetFullName (name.Name);
3406 public string GetFullName (string name)
3408 if (!IsExplicitImpl)
3412 // When dealing with explicit members a full interface type
3413 // name is added to member name to avoid possible name conflicts
3415 // We use CSharpName which gets us full name with benefit of
3416 // replacing predefined names which saves some space and name
3419 return TypeManager.CSharpName (InterfaceType) + "." + name;
3422 public override string GetSignatureForDocumentation ()
3425 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3427 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3430 public override bool IsUsed
3432 get { return IsExplicitImpl || base.IsUsed; }
3435 public override void SetConstraints (List<Constraints> constraints_list)
3437 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3438 Report.Error (460, Location,
3439 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3440 GetSignatureForError ());
3443 base.SetConstraints (constraints_list);
3447 public abstract class MemberBase : MemberCore
3449 protected FullNamedExpression type_expr;
3450 protected TypeSpec member_type;
3451 public new TypeDefinition Parent;
3453 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3454 : base (parent, name, attrs)
3456 this.Parent = parent;
3457 this.type_expr = type;
3458 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3463 public TypeSpec MemberType {
3469 public FullNamedExpression TypeExpression {
3478 // Main member define entry
3480 public override bool Define ()
3482 DoMemberTypeIndependentChecks ();
3485 // Returns false only when type resolution failed
3487 if (!ResolveMemberType ())
3490 DoMemberTypeDependentChecks ();
3495 // Any type_name independent checks
3497 protected virtual void DoMemberTypeIndependentChecks ()
3499 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3500 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3501 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3502 GetSignatureForError (), Parent.GetSignatureForError ());
3507 // Any type_name dependent checks
3509 protected virtual void DoMemberTypeDependentChecks ()
3511 // verify accessibility
3512 if (!IsAccessibleAs (MemberType)) {
3513 Report.SymbolRelatedToPreviousError (MemberType);
3514 if (this is Property)
3515 Report.Error (53, Location,
3516 "Inconsistent accessibility: property type `" +
3517 TypeManager.CSharpName (MemberType) + "' is less " +
3518 "accessible than property `" + GetSignatureForError () + "'");
3519 else if (this is Indexer)
3520 Report.Error (54, Location,
3521 "Inconsistent accessibility: indexer return type `" +
3522 TypeManager.CSharpName (MemberType) + "' is less " +
3523 "accessible than indexer `" + GetSignatureForError () + "'");
3524 else if (this is MethodCore) {
3525 if (this is Operator)
3526 Report.Error (56, Location,
3527 "Inconsistent accessibility: return type `" +
3528 TypeManager.CSharpName (MemberType) + "' is less " +
3529 "accessible than operator `" + GetSignatureForError () + "'");
3531 Report.Error (50, Location,
3532 "Inconsistent accessibility: return type `" +
3533 TypeManager.CSharpName (MemberType) + "' is less " +
3534 "accessible than method `" + GetSignatureForError () + "'");
3536 Report.Error (52, Location,
3537 "Inconsistent accessibility: field type `" +
3538 TypeManager.CSharpName (MemberType) + "' is less " +
3539 "accessible than field `" + GetSignatureForError () + "'");
3544 protected void IsTypePermitted ()
3546 if (MemberType.IsSpecialRuntimeType) {
3547 if (Parent is StateMachine) {
3548 Report.Error (4012, Location,
3549 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3550 MemberType.GetSignatureForError ());
3551 } else if (Parent is HoistedStoreyClass) {
3552 Report.Error (4013, Location,
3553 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3554 MemberType.GetSignatureForError ());
3556 Report.Error (610, Location,
3557 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3562 protected virtual bool CheckBase ()
3564 CheckProtectedModifier ();
3569 public override string GetSignatureForDocumentation ()
3571 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3574 protected virtual bool ResolveMemberType ()
3576 if (member_type != null)
3577 throw new InternalErrorException ("Multi-resolve");
3579 member_type = type_expr.ResolveAsType (this);
3580 return member_type != null;