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 if (Parent is TypeDefinition) {
353 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
356 var sb = new StringBuilder ();
357 CreateMetadataName (sb);
358 return sb.ToString ();
360 throw new NotImplementedException ();
364 public virtual void RemoveContainer (TypeContainer cont)
366 if (containers != null)
367 containers.Remove (cont);
369 var tc = Parent == Module ? Module : this;
370 tc.defined_names.Remove (cont.Basename);
373 public virtual void VerifyMembers ()
375 if (containers != null) {
376 foreach (TypeContainer tc in containers)
381 public override void WriteDebugSymbol (MonoSymbolFile file)
383 if (containers != null) {
384 foreach (TypeContainer tc in containers) {
385 tc.WriteDebugSymbol (file);
391 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
394 // Different context is needed when resolving type container base
395 // types. Type names come from the parent scope but type parameter
396 // names from the container scope.
398 public struct BaseContext : IMemberContext
402 public BaseContext (TypeContainer tc)
407 #region IMemberContext Members
409 public CompilerContext Compiler {
410 get { return tc.Compiler; }
413 public TypeSpec CurrentType {
414 get { return tc.Parent.CurrentType; }
417 public TypeParameters CurrentTypeParameters {
418 get { return tc.PartialContainer.CurrentTypeParameters; }
421 public MemberCore CurrentMemberDefinition {
425 public bool IsObsolete {
426 get { return tc.IsObsolete; }
429 public bool IsUnsafe {
430 get { return tc.IsUnsafe; }
433 public bool IsStatic {
434 get { return tc.IsStatic; }
437 public ModuleContainer Module {
438 get { return tc.Module; }
441 public string GetSignatureForError ()
443 return tc.GetSignatureForError ();
446 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
451 public FullNamedExpression LookupNamespaceAlias (string name)
453 return tc.Parent.LookupNamespaceAlias (name);
456 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
459 var tp = CurrentTypeParameters;
461 TypeParameter t = tp.Find (name);
463 return new TypeParameterExpr (t, loc);
467 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
477 GetHashCode = 1 << 1,
478 HasStaticFieldInitializer = 1 << 2
481 readonly List<MemberCore> members;
483 // Holds a list of fields that have initializers
484 protected List<FieldInitializer> initialized_fields;
486 // Holds a list of static fields that have initializers
487 protected List<FieldInitializer> initialized_static_fields;
489 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
491 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
494 // Points to the first non-static field added to the container.
496 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
497 // and the first one's as good as any.
499 protected FieldBase first_nonstatic_field;
502 // This one is computed after we can distinguish interfaces
503 // from classes from the arraylist `type_bases'
505 protected TypeSpec base_type;
506 FullNamedExpression base_type_expr; // TODO: It's temporary variable
507 protected TypeSpec[] iface_exprs;
509 protected List<FullNamedExpression> type_bases;
511 TypeDefinition InTransit;
513 public TypeBuilder TypeBuilder;
514 GenericTypeParameterBuilder[] all_tp_builders;
516 // All recursive type parameters put together sharing same
517 // TypeParameter instances
519 TypeParameters all_type_parameters;
521 public const string DefaultIndexerName = "Item";
523 bool has_normal_indexers;
525 protected bool requires_delayed_unmanagedtype_check;
527 bool members_defined;
528 bool members_defined_ok;
529 protected bool has_static_constructor;
531 private CachedMethods cached_method;
533 protected TypeSpec spec;
534 TypeSpec current_type;
536 public int DynamicSitesCounter;
537 public int AnonymousMethodsCounter;
539 static readonly string[] attribute_targets = new string[] { "type" };
542 /// The pending methods that need to be implemented
543 // (interfaces or abstract methods)
545 PendingImplementation pending;
547 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
548 : base (parent, name, attrs, kind)
550 PartialContainer = this;
551 members = new List<MemberCore> ();
556 public List<FullNamedExpression> BaseTypeExpressions {
562 public override TypeSpec CurrentType {
564 if (current_type == null) {
565 if (IsGenericOrParentIsGeneric) {
567 // Switch to inflated version as it's used by all expressions
569 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
570 current_type = spec.MakeGenericType (this, targs);
580 public override TypeParameters CurrentTypeParameters {
582 return PartialContainer.MemberName.TypeParameters;
586 int CurrentTypeParametersStartIndex {
588 int total = all_tp_builders.Length;
589 if (CurrentTypeParameters != null) {
590 return total - CurrentTypeParameters.Count;
596 public virtual AssemblyDefinition DeclaringAssembly {
598 return Module.DeclaringAssembly;
602 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
604 return Module.DeclaringAssembly;
608 public TypeSpec Definition {
614 public bool HasMembersDefined {
616 return members_defined;
620 public bool HasInstanceConstructor {
622 return (caching_flags & Flags.HasInstanceConstructor) != 0;
625 caching_flags |= Flags.HasInstanceConstructor;
629 // Indicated whether container has StructLayout attribute set Explicit
630 public bool HasExplicitLayout {
631 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
632 set { caching_flags |= Flags.HasExplicitLayout; }
635 public bool HasOperators {
637 return (caching_flags & Flags.HasUserOperators) != 0;
640 caching_flags |= Flags.HasUserOperators;
644 public bool HasStructLayout {
645 get { return (caching_flags & Flags.HasStructLayout) != 0; }
646 set { caching_flags |= Flags.HasStructLayout; }
649 public TypeSpec[] Interfaces {
655 public bool IsGenericOrParentIsGeneric {
657 return all_type_parameters != null;
661 public bool IsTopLevel {
663 return !(Parent is TypeDefinition);
667 public bool IsPartial {
669 return (ModFlags & Modifiers.PARTIAL) != 0;
673 bool ITypeDefinition.IsTypeForwarder {
680 // Returns true for secondary partial containers
684 return PartialContainer != this;
688 public MemberCache MemberCache {
690 return spec.MemberCache;
694 public List<MemberCore> Members {
700 string ITypeDefinition.Namespace {
703 while (p.Kind != MemberKind.Namespace)
706 return p.MemberName == null ? null : p.GetSignatureForError ();
710 public TypeParameters TypeParametersAll {
712 return all_type_parameters;
716 public override string[] ValidAttributeTargets {
718 return attribute_targets;
724 public override void Accept (StructuralVisitor visitor)
726 visitor.Visit (this);
729 public void AddMember (MemberCore symbol)
731 if (symbol.MemberName.ExplicitInterface != null) {
732 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
733 Report.Error (541, symbol.Location,
734 "`{0}': explicit interface declaration can only be declared in a class or struct",
735 symbol.GetSignatureForError ());
739 AddNameToContainer (symbol, symbol.MemberName.Basename);
740 members.Add (symbol);
743 public override void AddTypeContainer (TypeContainer tc)
745 AddNameToContainer (tc, tc.Basename);
747 if (containers == null)
748 containers = new List<TypeContainer> ();
751 base.AddTypeContainer (tc);
754 public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
758 if (containers == null)
759 containers = new List<TypeContainer> ();
761 base.AddCompilerGeneratedClass (c);
765 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
767 public virtual void AddNameToContainer (MemberCore symbol, string name)
769 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
773 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
774 PartialContainer.defined_names.Add (name, symbol);
778 if (symbol.EnableOverloadChecks (mc))
781 InterfaceMemberBase im = mc as InterfaceMemberBase;
782 if (im != null && im.IsExplicitImpl)
785 Report.SymbolRelatedToPreviousError (mc);
786 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
787 Error_MissingPartialModifier (symbol);
791 if (symbol is TypeParameter) {
792 Report.Error (692, symbol.Location,
793 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
795 Report.Error (102, symbol.Location,
796 "The type `{0}' already contains a definition for `{1}'",
797 GetSignatureForError (), name);
803 public void AddConstructor (Constructor c)
805 AddConstructor (c, false);
808 public void AddConstructor (Constructor c, bool isDefault)
810 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
812 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
814 if (is_static && c.ParameterInfo.IsEmpty) {
815 PartialContainer.has_static_constructor = true;
817 PartialContainer.HasInstanceConstructor = true;
823 public bool AddField (FieldBase field)
827 if ((field.ModFlags & Modifiers.STATIC) != 0)
830 var first_field = PartialContainer.first_nonstatic_field;
831 if (first_field == null) {
832 PartialContainer.first_nonstatic_field = field;
836 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
837 Report.SymbolRelatedToPreviousError (first_field.Parent);
838 Report.Warning (282, 3, field.Location,
839 "struct instance field `{0}' found in different declaration from instance field `{1}'",
840 field.GetSignatureForError (), first_field.GetSignatureForError ());
846 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
848 public void AddIndexer (Indexer i)
853 public void AddOperator (Operator op)
855 PartialContainer.HasOperators = true;
859 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
861 if (has_normal_indexers && a.Type == pa.DefaultMember) {
862 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
866 if (a.Type == pa.Required) {
867 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
871 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
874 public override AttributeTargets AttributeTargets {
876 throw new NotSupportedException ();
880 public TypeSpec BaseType {
882 return spec.BaseType;
886 protected virtual TypeAttributes TypeAttr {
888 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
892 public int TypeParametersCount {
894 return MemberName.Arity;
898 TypeParameterSpec[] ITypeDefinition.TypeParameters {
900 return PartialContainer.CurrentTypeParameters.Types;
904 public string GetAttributeDefaultMember ()
906 return indexer_name ?? DefaultIndexerName;
909 public bool IsComImport {
911 if (OptAttributes == null)
914 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
918 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
921 PartialContainer.RegisterFieldForInitialization (field, expression);
923 if ((field.ModFlags & Modifiers.STATIC) != 0){
924 if (initialized_static_fields == null) {
925 HasStaticFieldInitializer = true;
926 initialized_static_fields = new List<FieldInitializer> (4);
929 initialized_static_fields.Add (expression);
931 if (initialized_fields == null)
932 initialized_fields = new List<FieldInitializer> (4);
934 initialized_fields.Add (expression);
938 public void ResolveFieldInitializers (BlockContext ec)
940 Debug.Assert (!IsPartialPart);
943 if (initialized_static_fields == null)
946 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
948 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
949 for (i = 0; i < initialized_static_fields.Count; ++i) {
950 FieldInitializer fi = initialized_static_fields [i];
951 ExpressionStatement s = fi.ResolveStatement (ec);
953 s = EmptyExpressionStatement.Instance;
954 } else if (!fi.IsSideEffectFree) {
955 has_complex_initializer |= true;
961 for (i = 0; i < initialized_static_fields.Count; ++i) {
962 FieldInitializer fi = initialized_static_fields [i];
964 // Need special check to not optimize code like this
965 // static int a = b = 5;
968 if (!has_complex_initializer && fi.IsDefaultInitializer)
971 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
977 if (initialized_fields == null)
980 for (int i = 0; i < initialized_fields.Count; ++i) {
981 FieldInitializer fi = initialized_fields [i];
982 ExpressionStatement s = fi.ResolveStatement (ec);
987 // Field is re-initialized to its default value => removed
989 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
992 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
996 public override string DocComment {
1008 public PendingImplementation PendingImplementations {
1009 get { return pending; }
1012 internal override void GenerateDocComment (DocumentationBuilder builder)
1017 base.GenerateDocComment (builder);
1019 foreach (var member in members)
1020 member.GenerateDocComment (builder);
1023 public TypeSpec GetAttributeCoClass ()
1025 if (OptAttributes == null)
1028 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1032 return a.GetCoClassAttributeValue ();
1035 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1038 if (OptAttributes != null) {
1039 a = OptAttributes.Search (pa);
1045 return a.GetAttributeUsageAttribute ();
1048 public virtual CompilationSourceFile GetCompilationSourceFile ()
1050 TypeContainer ns = Parent;
1052 var sf = ns as CompilationSourceFile;
1060 public virtual void AddBasesForPart (List<FullNamedExpression> bases)
1066 /// This function computes the Base class and also the
1067 /// list of interfaces that the class or struct @c implements.
1069 /// The return value is an array (might be null) of
1070 /// interfaces implemented (as Types).
1072 /// The @base_class argument is set to the base object or null
1073 /// if this is `System.Object'.
1075 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1078 if (type_bases == null)
1081 int count = type_bases.Count;
1082 TypeSpec[] ifaces = null;
1083 var base_context = new BaseContext (this);
1084 for (int i = 0, j = 0; i < count; i++){
1085 FullNamedExpression fne = type_bases [i];
1087 var fne_resolved = fne.ResolveAsType (base_context);
1088 if (fne_resolved == null)
1091 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1092 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1093 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1094 GetSignatureForError ());
1099 base_type = fne_resolved;
1105 ifaces = new TypeSpec [count - i];
1107 if (fne_resolved.IsInterface) {
1108 for (int ii = 0; ii < j; ++ii) {
1109 if (fne_resolved == ifaces [ii]) {
1110 Report.Error (528, Location, "`{0}' is already listed in interface list",
1111 fne_resolved.GetSignatureForError ());
1116 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1117 Report.Error (61, fne.Location,
1118 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1119 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1122 Report.SymbolRelatedToPreviousError (fne_resolved);
1123 if (Kind != MemberKind.Class) {
1124 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1125 } else if (base_class != null)
1126 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1127 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1129 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1130 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1134 ifaces [j++] = fne_resolved;
1141 // Checks that some operators come in pairs:
1147 // They are matched based on the return type and the argument types
1149 void CheckPairedOperators ()
1151 bool has_equality_or_inequality = false;
1152 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1154 for (int i = 0; i < members.Count; ++i) {
1155 var o_a = members[i] as Operator;
1159 var o_type = o_a.OperatorType;
1160 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1161 has_equality_or_inequality = true;
1163 if (found_matched.Contains (o_type))
1166 var matching_type = o_a.GetMatchingOperator ();
1167 if (matching_type == Operator.OpType.TOP) {
1171 bool pair_found = false;
1172 for (int ii = i + 1; ii < members.Count; ++ii) {
1173 var o_b = members[ii] as Operator;
1174 if (o_b == null || o_b.OperatorType != matching_type)
1177 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1180 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1183 found_matched.Add (matching_type);
1189 Report.Error (216, o_a.Location,
1190 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1191 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1195 if (has_equality_or_inequality) {
1197 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1198 GetSignatureForError ());
1200 if (!HasGetHashCode)
1201 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1202 GetSignatureForError ());
1206 public override void CreateMetadataName (StringBuilder sb)
1208 if (Parent.MemberName != null) {
1209 Parent.CreateMetadataName (sb);
1211 if (sb.Length != 0) {
1216 sb.Append (MemberName.Basename);
1219 bool CreateTypeBuilder ()
1222 // Sets .size to 1 for structs with no instance fields
1224 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1226 var parent_def = Parent as TypeDefinition;
1227 if (parent_def == null) {
1228 var sb = new StringBuilder ();
1229 CreateMetadataName (sb);
1230 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1232 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1235 if (DeclaringAssembly.Importer != null)
1236 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1238 spec.SetMetaInfo (TypeBuilder);
1239 spec.MemberCache = new MemberCache (this);
1241 TypeParameters parentAllTypeParameters = null;
1242 if (parent_def != null) {
1243 spec.DeclaringType = Parent.CurrentType;
1244 parent_def.MemberCache.AddMember (spec);
1245 parentAllTypeParameters = parent_def.all_type_parameters;
1248 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1249 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1251 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1253 if (CurrentTypeParameters != null)
1254 CurrentTypeParameters.Define (all_tp_builders, spec, CurrentTypeParametersStartIndex, this);
1260 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1263 int parent_offset = 0;
1264 if (parentAllTypeParameters != null) {
1265 if (CurrentTypeParameters == null) {
1266 all_type_parameters = parentAllTypeParameters;
1267 return parentAllTypeParameters.GetAllNames ();
1270 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1271 all_type_parameters = new TypeParameters (names.Length);
1272 all_type_parameters.Add (parentAllTypeParameters);
1274 parent_offset = all_type_parameters.Count;
1275 for (int i = 0; i < parent_offset; ++i)
1276 names[i] = all_type_parameters[i].MemberName.Name;
1279 names = new string[CurrentTypeParameters.Count];
1282 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1283 if (all_type_parameters != null)
1284 all_type_parameters.Add (MemberName.TypeParameters[i]);
1286 var name = CurrentTypeParameters[i].MemberName.Name;
1287 names[parent_offset + i] = name;
1288 for (int ii = 0; ii < parent_offset + i; ++ii) {
1289 if (names[ii] != name)
1292 var tp = CurrentTypeParameters[i];
1293 var conflict = all_type_parameters[ii];
1295 tp.WarningParentNameConflict (conflict);
1299 if (all_type_parameters == null)
1300 all_type_parameters = CurrentTypeParameters;
1306 public SourceMethodBuilder CreateMethodSymbolEntry ()
1308 if (Module.DeclaringAssembly.SymbolWriter == null)
1311 var source_file = GetCompilationSourceFile ();
1312 if (source_file == null)
1315 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1319 // Creates a proxy base method call inside this container for hoisted base member calls
1321 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1323 Method proxy_method;
1326 // One proxy per base method is enough
1328 if (hoisted_base_call_proxies == null) {
1329 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1330 proxy_method = null;
1332 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1335 if (proxy_method == null) {
1336 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1337 var base_parameters = new Parameter[method.Parameters.Count];
1338 for (int i = 0; i < base_parameters.Length; ++i) {
1339 var base_param = method.Parameters.FixedParameters[i];
1340 base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
1341 base_param.Name, base_param.ModFlags, null, Location);
1342 base_parameters[i].Resolve (this, i);
1345 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1346 if (method.Parameters.HasArglist) {
1347 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1348 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1351 MemberName member_name;
1352 TypeArguments targs = null;
1353 if (method.IsGeneric) {
1355 // Copy all base generic method type parameters info
1357 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1358 var tparams = new TypeParameters ();
1360 targs = new TypeArguments ();
1361 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1362 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1363 var tp = hoisted_tparams[i];
1364 tparams.Add (new TypeParameter (tp, null, new MemberName (tp.Name, Location), null));
1366 targs.Add (new SimpleName (tp.Name, Location));
1367 targs.Arguments[i] = tp;
1370 member_name = new MemberName (name, tparams, Location);
1372 member_name = new MemberName (name);
1375 // Compiler generated proxy
1376 proxy_method = new Method (this, new TypeExpression (method.ReturnType, Location),
1377 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1378 member_name, cloned_params, null);
1380 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1381 IsCompilerGenerated = true
1384 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1385 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1387 mg.SetTypeArguments (rc, targs);
1389 // Get all the method parameters and pass them as arguments
1390 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1391 Statement statement;
1392 if (method.ReturnType.Kind == MemberKind.Void)
1393 statement = new StatementExpression (real_base_call);
1395 statement = new Return (real_base_call, Location);
1397 block.AddStatement (statement);
1398 proxy_method.Block = block;
1400 members.Add (proxy_method);
1401 proxy_method.Define ();
1403 hoisted_base_call_proxies.Add (method, proxy_method);
1406 return proxy_method.Spec;
1409 protected bool DefineBaseTypes ()
1411 iface_exprs = ResolveBaseTypes (out base_type_expr);
1414 if (IsPartialPart) {
1415 set_base_type = false;
1417 if (base_type_expr != null) {
1418 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1419 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1420 Report.Error (263, Location,
1421 "Partial declarations of `{0}' must not specify different base classes",
1422 GetSignatureForError ());
1424 PartialContainer.base_type_expr = base_type_expr;
1425 PartialContainer.base_type = base_type;
1426 set_base_type = true;
1430 if (iface_exprs != null) {
1431 if (PartialContainer.iface_exprs == null)
1432 PartialContainer.iface_exprs = iface_exprs;
1434 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1435 foreach (var iface_partial in iface_exprs) {
1436 if (ifaces.Contains (iface_partial))
1439 ifaces.Add (iface_partial);
1442 PartialContainer.iface_exprs = ifaces.ToArray ();
1446 PartialContainer.members.AddRange (members);
1447 if (containers != null) {
1448 if (PartialContainer.containers == null)
1449 PartialContainer.containers = new List<TypeContainer> ();
1451 PartialContainer.containers.AddRange (containers);
1454 members_defined = members_defined_ok = true;
1455 caching_flags |= Flags.CloseTypeCreated;
1457 set_base_type = true;
1460 var cycle = CheckRecursiveDefinition (this);
1461 if (cycle != null) {
1462 Report.SymbolRelatedToPreviousError (cycle);
1463 if (this is Interface) {
1464 Report.Error (529, Location,
1465 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1466 GetSignatureForError (), cycle.GetSignatureForError ());
1470 Report.Error (146, Location,
1471 "Circular base class dependency involving `{0}' and `{1}'",
1472 GetSignatureForError (), cycle.GetSignatureForError ());
1478 if (iface_exprs != null) {
1479 foreach (var iface_type in iface_exprs) {
1480 // Prevents a crash, the interface might not have been resolved: 442144
1481 if (iface_type == null)
1484 if (!spec.AddInterfaceDefined (iface_type))
1487 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1489 // Ensure the base is always setup
1490 var compiled_iface = iface_type.MemberDefinition as Interface;
1491 if (compiled_iface != null) {
1492 // TODO: Need DefineBaseType only
1493 compiled_iface.DefineContainer ();
1496 if (iface_type.Interfaces != null) {
1497 var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
1498 for (int i = 0; i < base_ifaces.Count; ++i) {
1499 var ii_iface_type = base_ifaces[i];
1500 if (spec.AddInterfaceDefined (ii_iface_type)) {
1501 TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
1503 if (ii_iface_type.Interfaces != null)
1504 base_ifaces.AddRange (ii_iface_type.Interfaces);
1511 if (Kind == MemberKind.Interface) {
1512 spec.BaseType = Compiler.BuiltinTypes.Object;
1516 if (set_base_type) {
1517 if (base_type != null) {
1518 spec.BaseType = base_type;
1520 // Set base type after type creation
1521 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1523 TypeBuilder.SetParent (null);
1530 public override void PrepareEmit ()
1532 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1535 foreach (var member in members) {
1536 var pm = member as IParametersMember;
1539 var p = pm.Parameters;
1543 ((ParametersCompiled) p).ResolveDefaultValues (member);
1546 var c = member as Const;
1551 base.PrepareEmit ();
1555 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1557 public override bool CreateContainer ()
1559 if (TypeBuilder != null)
1565 if (IsPartialPart) {
1566 spec = PartialContainer.spec;
1567 TypeBuilder = PartialContainer.TypeBuilder;
1568 all_tp_builders = PartialContainer.all_tp_builders;
1569 all_type_parameters = PartialContainer.all_type_parameters;
1571 if (!CreateTypeBuilder ()) {
1577 return base.CreateContainer ();
1580 protected override void DoDefineContainer ()
1584 DoResolveTypeParameters ();
1588 // Replaces normal spec with predefined one when compiling corlib
1589 // and this type container defines predefined type
1591 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1593 // When compiling build-in types we start with two
1594 // version of same type. One is of BuiltinTypeSpec and
1595 // second one is ordinary TypeSpec. The unification
1596 // happens at later stage when we know which type
1597 // really matches the builtin type signature. However
1598 // that means TypeSpec create during CreateType of this
1599 // type has to be replaced with builtin one
1601 spec.SetMetaInfo (TypeBuilder);
1602 spec.MemberCache = this.spec.MemberCache;
1603 spec.DeclaringType = this.spec.DeclaringType;
1606 current_type = null;
1609 void UpdateTypeParameterConstraints (TypeDefinition part)
1611 for (int i = 0; i < CurrentTypeParameters.Count; i++) {
1612 if (CurrentTypeParameters[i].AddPartialConstraints (part, part.MemberName.TypeParameters[i]))
1615 Report.SymbolRelatedToPreviousError (Location, "");
1616 Report.Error (265, part.Location,
1617 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1618 GetSignatureForError (), CurrentTypeParameters[i].GetSignatureForError ());
1622 public override void RemoveContainer (TypeContainer cont)
1624 base.RemoveContainer (cont);
1625 Members.Remove (cont);
1626 Cache.Remove (cont.Basename);
1629 protected virtual bool DoResolveTypeParameters ()
1631 var tparams = CurrentTypeParameters;
1632 if (tparams == null)
1635 var base_context = new BaseContext (this);
1636 for (int i = 0; i < tparams.Count; ++i) {
1637 var tp = tparams[i];
1639 if (!tp.ResolveConstraints (base_context)) {
1645 if (IsPartialPart) {
1646 PartialContainer.UpdateTypeParameterConstraints (this);
1652 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1654 if (InTransit != null)
1659 if (base_type != null) {
1660 var ptc = base_type.MemberDefinition as TypeDefinition;
1661 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1665 if (iface_exprs != null) {
1666 foreach (var iface in iface_exprs) {
1667 // the interface might not have been resolved, prevents a crash, see #442144
1670 var ptc = iface.MemberDefinition as Interface;
1671 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1676 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1684 /// Populates our TypeBuilder with fields and methods
1686 public sealed override bool Define ()
1688 if (members_defined)
1689 return members_defined_ok;
1691 members_defined_ok = DoDefineMembers ();
1692 members_defined = true;
1696 return members_defined_ok;
1699 protected virtual bool DoDefineMembers ()
1701 Debug.Assert (!IsPartialPart);
1703 if (iface_exprs != null) {
1704 foreach (var iface_type in iface_exprs) {
1705 if (iface_type == null)
1708 // Ensure the base is always setup
1709 var compiled_iface = iface_type.MemberDefinition as Interface;
1710 if (compiled_iface != null)
1711 compiled_iface.Define ();
1713 if (Kind == MemberKind.Interface)
1714 MemberCache.AddInterface (iface_type);
1716 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1717 if (oa != null && !IsObsolete)
1718 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1720 if (iface_type.Arity > 0) {
1721 // TODO: passing `this' is wrong, should be base type iface instead
1722 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1724 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1725 Report.Error (1966, Location,
1726 "`{0}': cannot implement a dynamic interface `{1}'",
1727 GetSignatureForError (), iface_type.GetSignatureForError ());
1732 if (iface_type.IsGenericOrParentIsGeneric) {
1733 if (spec.Interfaces != null) {
1734 foreach (var prev_iface in iface_exprs) {
1735 if (prev_iface == iface_type)
1738 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1741 Report.Error (695, Location,
1742 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1743 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1750 if (base_type != null) {
1752 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1754 if (base_type_expr != null) {
1755 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1756 if (obsolete_attr != null && !IsObsolete)
1757 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1759 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1760 Report.Error (698, base_type_expr.Location,
1761 "A generic type cannot derive from `{0}' because it is an attribute class",
1762 base_type.GetSignatureForError ());
1766 if (base_type.Interfaces != null) {
1767 foreach (var iface in base_type.Interfaces)
1768 spec.AddInterface (iface);
1771 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1772 if (baseContainer != null) {
1773 baseContainer.Define ();
1776 // It can trigger define of this type (for generic types only)
1778 if (HasMembersDefined)
1783 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1784 pending = PendingImplementation.GetPendingImplementations (this);
1787 var count = members.Count;
1788 for (int i = 0; i < count; ++i) {
1789 var mc = members[i] as InterfaceMemberBase;
1790 if (mc == null || !mc.IsExplicitImpl)
1795 } catch (Exception e) {
1796 throw new InternalErrorException (mc, e);
1800 for (int i = 0; i < count; ++i) {
1801 var mc = members[i] as InterfaceMemberBase;
1802 if (mc != null && mc.IsExplicitImpl)
1805 if (members[i] is TypeContainer)
1809 members[i].Define ();
1810 } catch (Exception e) {
1811 throw new InternalErrorException (members[i], e);
1816 CheckPairedOperators ();
1819 if (requires_delayed_unmanagedtype_check) {
1820 requires_delayed_unmanagedtype_check = false;
1821 foreach (var member in members) {
1822 var f = member as Field;
1823 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1824 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1828 ComputeIndexerName();
1830 if (HasEquals && !HasGetHashCode) {
1831 Report.Warning (659, 3, Location,
1832 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1835 if (Kind == MemberKind.Interface && iface_exprs != null) {
1836 MemberCache.RemoveHiddenMembers (spec);
1842 void ComputeIndexerName ()
1844 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1845 if (indexers == null)
1848 string class_indexer_name = null;
1851 // Check normal indexers for consistent name, explicit interface implementation
1852 // indexers are ignored
1854 foreach (var indexer in indexers) {
1856 // FindMembers can return unfiltered full hierarchy names
1858 if (indexer.DeclaringType != spec)
1861 has_normal_indexers = true;
1863 if (class_indexer_name == null) {
1864 indexer_name = class_indexer_name = indexer.Name;
1868 if (indexer.Name != class_indexer_name)
1869 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1870 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1874 void EmitIndexerName ()
1876 if (!has_normal_indexers)
1879 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1883 var encoder = new AttributeEncoder ();
1884 encoder.Encode (GetAttributeDefaultMember ());
1885 encoder.EncodeEmptyNamedArguments ();
1887 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1890 public override void VerifyMembers ()
1893 // Check for internal or private fields that were never assigned
1895 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1896 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1897 foreach (var member in members) {
1898 if (member is Event) {
1900 // An event can be assigned from same class only, so we can report
1901 // this warning for all accessibility modes
1904 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1909 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1910 if (is_type_exposed)
1913 member.SetIsUsed ();
1916 var f = member as Field;
1920 if (!member.IsUsed) {
1921 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1922 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1924 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1925 member.GetSignatureForError ());
1930 if ((f.caching_flags & Flags.IsAssigned) != 0)
1934 // Only report 649 on level 4
1936 if (Compiler.Settings.WarningLevel < 4)
1940 // Don't be pedantic when type requires specific layout
1942 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1945 Constant c = New.Constantify (f.MemberType, f.Location);
1948 value = c.GetValueAsLiteral ();
1949 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
1956 value = " `" + value + "'";
1958 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
1959 f.GetSignatureForError (), value);
1963 base.VerifyMembers ();
1966 public override void Emit ()
1968 if (OptAttributes != null)
1969 OptAttributes.Emit ();
1971 if (!IsCompilerGenerated) {
1973 MemberSpec candidate;
1974 bool overrides = false;
1975 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
1976 if (conflict_symbol == null && candidate == null) {
1977 if ((ModFlags & Modifiers.NEW) != 0)
1978 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1979 GetSignatureForError ());
1981 if ((ModFlags & Modifiers.NEW) == 0) {
1982 if (candidate == null)
1983 candidate = conflict_symbol;
1985 Report.SymbolRelatedToPreviousError (candidate);
1986 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1987 GetSignatureForError (), candidate.GetSignatureForError ());
1992 // Run constraints check on all possible generic types
1993 if (base_type != null && base_type_expr != null) {
1994 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
1997 if (iface_exprs != null) {
1998 foreach (var iface_type in iface_exprs) {
1999 if (iface_type == null)
2002 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2007 if (all_tp_builders != null) {
2008 int current_starts_index = CurrentTypeParametersStartIndex;
2009 for (int i = 0; i < all_tp_builders.Length; i++) {
2010 if (i < current_starts_index) {
2011 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2013 var tp = CurrentTypeParameters [i - current_starts_index];
2014 tp.CheckGenericConstraints (!IsObsolete);
2020 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2021 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2024 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2025 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2030 for (int i = 0; i < members.Count; i++)
2034 CheckAttributeClsCompliance ();
2036 if (pending != null)
2037 pending.VerifyPendingMethods ();
2041 void CheckAttributeClsCompliance ()
2043 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2046 foreach (var m in members) {
2047 var c = m as Constructor;
2051 if (c.HasCompliantArgs)
2055 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2058 public sealed override void EmitContainer ()
2060 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2066 public override void CloseContainer ()
2068 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2071 // Close base type container first to avoid TypeLoadException
2072 if (spec.BaseType != null) {
2073 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2074 if (btype != null) {
2075 btype.CloseContainer ();
2077 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2083 caching_flags |= Flags.CloseTypeCreated;
2084 TypeBuilder.CreateType ();
2085 } catch (TypeLoadException) {
2087 // This is fine, the code still created the type
2089 } catch (Exception e) {
2090 throw new InternalErrorException (this, e);
2093 base.CloseContainer ();
2096 initialized_fields = null;
2097 initialized_static_fields = null;
2099 OptAttributes = null;
2103 // Performs the validation on a Method's modifiers (properties have
2104 // the same properties).
2106 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2108 public bool MethodModifiersValid (MemberCore mc)
2110 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2111 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2113 var flags = mc.ModFlags;
2116 // At most one of static, virtual or override
2118 if ((flags & Modifiers.STATIC) != 0){
2119 if ((flags & vao) != 0){
2120 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2121 mc.GetSignatureForError ());
2126 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2127 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2128 mc.GetSignatureForError ());
2133 // If the declaration includes the abstract modifier, then the
2134 // declaration does not include static, virtual or extern
2136 if ((flags & Modifiers.ABSTRACT) != 0){
2137 if ((flags & Modifiers.EXTERN) != 0){
2139 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2143 if ((flags & Modifiers.SEALED) != 0) {
2144 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2148 if ((flags & Modifiers.VIRTUAL) != 0){
2149 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2153 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2154 Report.SymbolRelatedToPreviousError (this);
2155 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2156 mc.GetSignatureForError (), GetSignatureForError ());
2161 if ((flags & Modifiers.PRIVATE) != 0){
2162 if ((flags & vao) != 0){
2163 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2168 if ((flags & Modifiers.SEALED) != 0){
2169 if ((flags & Modifiers.OVERRIDE) == 0){
2170 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2178 protected override bool VerifyClsCompliance ()
2180 if (!base.VerifyClsCompliance ())
2183 // Check all container names for user classes
2184 if (Kind != MemberKind.Delegate)
2185 MemberCache.VerifyClsCompliance (Definition, Report);
2187 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2188 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2189 GetSignatureForError (), BaseType.GetSignatureForError ());
2195 /// Performs checks for an explicit interface implementation. First it
2196 /// checks whether the `interface_type' is a base inteface implementation.
2197 /// Then it checks whether `name' exists in the interface type.
2199 public bool VerifyImplements (InterfaceMemberBase mb)
2201 var ifaces = spec.Interfaces;
2202 if (ifaces != null) {
2203 foreach (TypeSpec t in ifaces){
2204 if (t == mb.InterfaceType)
2209 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2210 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2211 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2216 // Used for visiblity checks to tests whether this definition shares
2217 // base type baseType, it does member-definition search
2219 public bool IsBaseTypeDefinition (TypeSpec baseType)
2221 // RootContext check
2222 if (TypeBuilder == null)
2227 if (type.MemberDefinition == baseType.MemberDefinition)
2230 type = type.BaseType;
2231 } while (type != null);
2236 public override bool IsClsComplianceRequired ()
2239 return PartialContainer.IsClsComplianceRequired ();
2241 return base.IsClsComplianceRequired ();
2244 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2246 return Module.DeclaringAssembly == assembly;
2249 public virtual bool IsUnmanagedType ()
2254 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2256 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2260 // Public function used to locate types.
2262 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2264 // Returns: Type or null if they type can not be found.
2266 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2268 FullNamedExpression e;
2269 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2275 var tp = CurrentTypeParameters;
2277 TypeParameter tparam = tp.Find (name);
2279 e = new TypeParameterExpr (tparam, Location.Null);
2284 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2286 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2287 e = new TypeExpression (t, Location.Null);
2289 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2293 // TODO MemberCache: How to cache arity stuff ?
2294 if (arity == 0 && mode == LookupMode.Normal)
2300 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2302 // Has any nested type
2303 // Does not work, because base type can have
2304 //if (PartialContainer.Types == null)
2307 var container = PartialContainer.CurrentType;
2308 return MemberCache.FindNestedType (container, name, arity);
2311 public void Mark_HasEquals ()
2313 cached_method |= CachedMethods.Equals;
2316 public void Mark_HasGetHashCode ()
2318 cached_method |= CachedMethods.GetHashCode;
2321 public override void WriteDebugSymbol (MonoSymbolFile file)
2326 foreach (var m in members) {
2327 m.WriteDebugSymbol (file);
2332 /// Method container contains Equals method
2334 public bool HasEquals {
2336 return (cached_method & CachedMethods.Equals) != 0;
2341 /// Method container contains GetHashCode method
2343 public bool HasGetHashCode {
2345 return (cached_method & CachedMethods.GetHashCode) != 0;
2349 public bool HasStaticFieldInitializer {
2351 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2355 cached_method |= CachedMethods.HasStaticFieldInitializer;
2357 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2361 public override string DocCommentHeader {
2362 get { return "T:"; }
2366 public abstract class ClassOrStruct : TypeDefinition
2368 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2370 SecurityType declarative_security;
2372 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2373 : base (parent, name, attrs, kind)
2377 protected override TypeAttributes TypeAttr {
2379 TypeAttributes ta = base.TypeAttr;
2380 if (!has_static_constructor)
2381 ta |= TypeAttributes.BeforeFieldInit;
2383 if (Kind == MemberKind.Class) {
2384 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2386 ta |= StaticClassAttribute;
2388 ta |= TypeAttributes.SequentialLayout;
2395 public override void AddNameToContainer (MemberCore symbol, string name)
2397 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2398 if (symbol is TypeParameter) {
2399 Report.Error (694, symbol.Location,
2400 "Type parameter `{0}' has same name as containing type, or method",
2401 symbol.GetSignatureForError ());
2405 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2406 if (imb == null || !imb.IsExplicitImpl) {
2407 Report.SymbolRelatedToPreviousError (this);
2408 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2409 symbol.GetSignatureForError ());
2414 base.AddNameToContainer (symbol, name);
2417 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2419 if (a.IsValidSecurityAttribute ()) {
2420 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2424 if (a.Type == pa.StructLayout) {
2425 PartialContainer.HasStructLayout = true;
2426 if (a.IsExplicitLayoutKind ())
2427 PartialContainer.HasExplicitLayout = true;
2430 if (a.Type == pa.Dynamic) {
2431 a.Error_MisusedDynamicAttribute ();
2435 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2439 /// Defines the default constructors
2441 protected Constructor DefineDefaultConstructor (bool is_static)
2443 // The default instance constructor is public
2444 // If the class is abstract, the default constructor is protected
2445 // The default static constructor is private
2449 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2451 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2454 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2455 c.Initializer = new GeneratedBaseInitializer (Location);
2457 AddConstructor (c, true);
2458 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2459 IsCompilerGenerated = true
2465 protected override bool DoDefineMembers ()
2467 CheckProtectedModifier ();
2469 base.DoDefineMembers ();
2474 public override void Emit ()
2476 if (!has_static_constructor && HasStaticFieldInitializer) {
2477 var c = DefineDefaultConstructor (true);
2483 if (declarative_security != null) {
2484 foreach (var de in declarative_security) {
2486 TypeBuilder.__AddDeclarativeSecurity (de);
2488 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2496 public sealed class Class : ClassOrStruct
2498 const Modifiers AllowedModifiers =
2501 Modifiers.PROTECTED |
2502 Modifiers.INTERNAL |
2504 Modifiers.ABSTRACT |
2509 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2510 : base (parent, name, attrs, MemberKind.Class)
2512 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2513 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2514 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2517 public override void Accept (StructuralVisitor visitor)
2519 visitor.Visit (this);
2522 public override void AddBasesForPart (List<FullNamedExpression> bases)
2524 var pmn = MemberName;
2525 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2526 Report.Error (537, Location,
2527 "The class System.Object cannot have a base class or implement an interface.");
2529 base.AddBasesForPart (bases);
2532 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2534 if (a.Type == pa.AttributeUsage) {
2535 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2536 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2540 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2541 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2545 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2546 a.Error_MissingGuidAttribute ();
2550 if (a.Type == pa.Extension) {
2551 a.Error_MisusedExtensionAttribute ();
2555 if (a.Type.IsConditionallyExcluded (this, Location))
2558 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2561 public override AttributeTargets AttributeTargets {
2563 return AttributeTargets.Class;
2567 protected override bool DoDefineMembers ()
2569 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2570 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2573 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2574 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2578 foreach (var m in Members) {
2579 if (m is Operator) {
2580 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2584 if (m is Destructor) {
2585 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2590 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2594 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2597 if (m is Constructor) {
2598 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2602 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2605 if (!PartialContainer.HasInstanceConstructor)
2606 DefineDefaultConstructor (false);
2609 return base.DoDefineMembers ();
2612 public override void Emit ()
2616 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2617 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2619 if (base_type != null && base_type.HasDynamicElement) {
2620 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2624 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2626 var ifaces = base.ResolveBaseTypes (out base_class);
2628 if (base_class == null) {
2629 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2630 base_type = Compiler.BuiltinTypes.Object;
2632 if (base_type.IsGenericParameter){
2633 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2634 GetSignatureForError (), base_type.GetSignatureForError ());
2635 } else if (base_type.IsStatic) {
2636 Report.SymbolRelatedToPreviousError (base_type);
2637 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2638 GetSignatureForError (), base_type.GetSignatureForError ());
2639 } else if (base_type.IsSealed) {
2640 Report.SymbolRelatedToPreviousError (base_type);
2641 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2642 GetSignatureForError (), base_type.GetSignatureForError ());
2643 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2644 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2645 GetSignatureForError (), base_type.GetSignatureForError ());
2648 switch (base_type.BuiltinType) {
2649 case BuiltinTypeSpec.Type.Enum:
2650 case BuiltinTypeSpec.Type.ValueType:
2651 case BuiltinTypeSpec.Type.MulticastDelegate:
2652 case BuiltinTypeSpec.Type.Delegate:
2653 case BuiltinTypeSpec.Type.Array:
2654 if (!(spec is BuiltinTypeSpec)) {
2655 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2656 GetSignatureForError (), base_type.GetSignatureForError ());
2658 base_type = Compiler.BuiltinTypes.Object;
2663 if (!IsAccessibleAs (base_type)) {
2664 Report.SymbolRelatedToPreviousError (base_type);
2665 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2666 base_type.GetSignatureForError (), GetSignatureForError ());
2670 if (PartialContainer.IsStatic && ifaces != null) {
2671 foreach (var t in ifaces)
2672 Report.SymbolRelatedToPreviousError (t);
2673 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2679 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2680 /// Valid only for attribute classes.
2681 public override string[] ConditionalConditions ()
2683 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2686 caching_flags &= ~Flags.Excluded_Undetected;
2688 if (OptAttributes == null)
2691 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2695 string[] conditions = new string[attrs.Length];
2696 for (int i = 0; i < conditions.Length; ++i)
2697 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2699 caching_flags |= Flags.Excluded;
2704 public sealed class Struct : ClassOrStruct
2706 bool is_unmanaged, has_unmanaged_check_done;
2710 // Modifiers allowed in a struct declaration
2712 const Modifiers AllowedModifiers =
2715 Modifiers.PROTECTED |
2716 Modifiers.INTERNAL |
2720 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2721 : base (parent, name, attrs, MemberKind.Struct)
2723 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2724 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2725 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2728 public override AttributeTargets AttributeTargets {
2730 return AttributeTargets.Struct;
2734 public override void Accept (StructuralVisitor visitor)
2736 visitor.Visit (this);
2739 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2741 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2744 // When struct constains fixed fixed and struct layout has explicitly
2745 // set CharSet, its value has to be propagated to compiler generated
2748 if (a.Type == pa.StructLayout) {
2749 var value = a.GetNamedValue ("CharSet");
2753 for (int i = 0; i < Members.Count; ++i) {
2754 FixedField ff = Members [i] as FixedField;
2758 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2763 bool CheckStructCycles ()
2769 foreach (var member in Members) {
2770 var field = member as Field;
2774 TypeSpec ftype = field.Spec.MemberType;
2775 if (!ftype.IsStruct)
2778 if (ftype is BuiltinTypeSpec)
2781 foreach (var targ in ftype.TypeArguments) {
2782 if (!CheckFieldTypeCycle (targ)) {
2783 Report.Error (523, field.Location,
2784 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2785 field.GetSignatureForError (), ftype.GetSignatureForError ());
2791 // Static fields of exactly same type are allowed
2793 if (field.IsStatic && ftype == CurrentType)
2796 if (!CheckFieldTypeCycle (ftype)) {
2797 Report.Error (523, field.Location,
2798 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2799 field.GetSignatureForError (), ftype.GetSignatureForError ());
2808 static bool CheckFieldTypeCycle (TypeSpec ts)
2810 var fts = ts.MemberDefinition as Struct;
2814 return fts.CheckStructCycles ();
2817 public override void Emit ()
2819 CheckStructCycles ();
2824 public override bool IsUnmanagedType ()
2826 if (has_unmanaged_check_done)
2827 return is_unmanaged;
2829 if (requires_delayed_unmanagedtype_check)
2832 var parent_def = Parent.PartialContainer;
2833 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2834 has_unmanaged_check_done = true;
2838 if (first_nonstatic_field != null) {
2839 requires_delayed_unmanagedtype_check = true;
2841 foreach (var member in Members) {
2842 var f = member as Field;
2849 // It can happen when recursive unmanaged types are defined
2850 // struct S { S* s; }
2851 TypeSpec mt = f.MemberType;
2859 has_unmanaged_check_done = true;
2863 has_unmanaged_check_done = true;
2866 is_unmanaged = true;
2870 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2872 var ifaces = base.ResolveBaseTypes (out base_class);
2873 base_type = Compiler.BuiltinTypes.ValueType;
2877 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2879 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2880 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2881 field.GetSignatureForError ());
2884 base.RegisterFieldForInitialization (field, expression);
2892 public sealed class Interface : TypeDefinition {
2895 /// Modifiers allowed in a class declaration
2897 const Modifiers AllowedModifiers =
2900 Modifiers.PROTECTED |
2901 Modifiers.INTERNAL |
2905 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2906 : base (parent, name, attrs, MemberKind.Interface)
2908 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2910 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2911 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2916 public override AttributeTargets AttributeTargets {
2918 return AttributeTargets.Interface;
2922 protected override TypeAttributes TypeAttr {
2924 const TypeAttributes DefaultTypeAttributes =
2925 TypeAttributes.AutoLayout |
2926 TypeAttributes.Abstract |
2927 TypeAttributes.Interface;
2929 return base.TypeAttr | DefaultTypeAttributes;
2935 public override void Accept (StructuralVisitor visitor)
2937 visitor.Visit (this);
2940 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2942 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2943 a.Error_MissingGuidAttribute ();
2947 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2950 protected override bool VerifyClsCompliance ()
2952 if (!base.VerifyClsCompliance ())
2955 if (iface_exprs != null) {
2956 foreach (var iface in iface_exprs) {
2957 if (iface.IsCLSCompliant ())
2960 Report.SymbolRelatedToPreviousError (iface);
2961 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2962 GetSignatureForError (), TypeManager.CSharpName (iface));
2970 public abstract class InterfaceMemberBase : MemberBase
2973 // Common modifiers allowed in a class declaration
2975 protected const Modifiers AllowedModifiersClass =
2978 Modifiers.PROTECTED |
2979 Modifiers.INTERNAL |
2984 Modifiers.OVERRIDE |
2985 Modifiers.ABSTRACT |
2990 // Common modifiers allowed in a struct declaration
2992 protected const Modifiers AllowedModifiersStruct =
2995 Modifiers.PROTECTED |
2996 Modifiers.INTERNAL |
2999 Modifiers.OVERRIDE |
3004 // Common modifiers allowed in a interface declaration
3006 protected const Modifiers AllowedModifiersInterface =
3011 // Whether this is an interface member.
3013 public bool IsInterface;
3016 // If true, this is an explicit interface implementation
3018 public readonly bool IsExplicitImpl;
3020 protected bool is_external_implementation;
3023 // The interface type we are explicitly implementing
3025 public TypeSpec InterfaceType;
3028 // The method we're overriding if this is an override method.
3030 protected MethodSpec base_method;
3032 readonly Modifiers explicit_mod_flags;
3033 public MethodAttributes flags;
3035 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3036 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3038 IsInterface = parent.Kind == MemberKind.Interface;
3039 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3040 explicit_mod_flags = mod;
3043 public abstract Variance ExpectedMemberTypeVariance { get; }
3045 protected override bool CheckBase ()
3047 if (!base.CheckBase ())
3050 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3051 CheckForDuplications ();
3056 // For System.Object only
3057 if (Parent.BaseType == null)
3060 MemberSpec candidate;
3061 bool overrides = false;
3062 var base_member = FindBaseMember (out candidate, ref overrides);
3064 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3065 if (base_member == null) {
3066 if (candidate == null) {
3067 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3068 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3069 "object.Finalize()");
3071 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3072 GetSignatureForError (), SimpleName.GetMemberType (this));
3075 Report.SymbolRelatedToPreviousError (candidate);
3077 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3078 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3079 else if (this is PropertyBase)
3080 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3081 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3083 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3084 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3091 // Handles ambiguous overrides
3093 if (candidate != null) {
3094 Report.SymbolRelatedToPreviousError (candidate);
3095 Report.SymbolRelatedToPreviousError (base_member);
3097 // Get member definition for error reporting
3098 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3099 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3101 Report.Error (462, Location,
3102 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3103 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3106 if (!CheckOverrideAgainstBase (base_member))
3109 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3111 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3112 Report.SymbolRelatedToPreviousError (base_member);
3113 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3114 GetSignatureForError (), base_member.GetSignatureForError ());
3117 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3118 Report.SymbolRelatedToPreviousError (base_member);
3119 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3120 GetSignatureForError (), base_member.GetSignatureForError ());
3124 base_method = base_member as MethodSpec;
3128 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3129 base_member = candidate;
3131 if (base_member == null) {
3132 if ((ModFlags & Modifiers.NEW) != 0) {
3133 if (base_member == null) {
3134 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3135 GetSignatureForError ());
3139 if ((ModFlags & Modifiers.NEW) == 0) {
3140 ModFlags |= Modifiers.NEW;
3141 if (!IsCompilerGenerated) {
3142 Report.SymbolRelatedToPreviousError (base_member);
3143 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3144 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",
3145 GetSignatureForError (), base_member.GetSignatureForError ());
3147 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3148 GetSignatureForError (), base_member.GetSignatureForError ());
3153 if (!IsInterface && base_member.IsAbstract && !overrides) {
3154 Report.SymbolRelatedToPreviousError (base_member);
3155 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3156 GetSignatureForError (), base_member.GetSignatureForError ());
3163 protected virtual bool CheckForDuplications ()
3165 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3169 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3170 // that have been defined.
3172 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3176 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3177 Report.SymbolRelatedToPreviousError (base_member);
3178 Report.Error (506, Location,
3179 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3180 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3184 // Now we check that the overriden method is not final
3185 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3186 Report.SymbolRelatedToPreviousError (base_member);
3187 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3188 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3192 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3193 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3194 Report.SymbolRelatedToPreviousError (base_member);
3195 if (this is PropertyBasedMember) {
3196 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3197 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3199 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3200 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3208 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3210 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3211 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3213 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3215 // It must be at least "protected"
3217 if ((thisp & Modifiers.PROTECTED) == 0) {
3222 // when overriding protected internal, the method can be declared
3223 // protected internal only within the same assembly or assembly
3224 // which has InternalsVisibleTo
3226 if ((thisp & Modifiers.INTERNAL) != 0) {
3227 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3231 // protected overriding protected internal inside same assembly
3232 // requires internal modifier as well
3234 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3241 return thisp == base_classp;
3244 public override bool Define ()
3247 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3248 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3250 flags = MethodAttributes.Public |
3251 MethodAttributes.Abstract |
3252 MethodAttributes.HideBySig |
3253 MethodAttributes.NewSlot |
3254 MethodAttributes.Virtual;
3256 Parent.PartialContainer.MethodModifiersValid (this);
3258 flags = ModifiersExtensions.MethodAttr (ModFlags);
3261 if (IsExplicitImpl) {
3262 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3263 if (InterfaceType == null)
3266 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3267 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3268 GetSignatureForError ());
3271 if (!InterfaceType.IsInterface) {
3272 Report.SymbolRelatedToPreviousError (InterfaceType);
3273 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3274 TypeManager.CSharpName (InterfaceType));
3276 Parent.PartialContainer.VerifyImplements (this);
3279 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3282 return base.Define ();
3285 protected bool DefineParameters (ParametersCompiled parameters)
3287 if (!parameters.Resolve (this))
3291 for (int i = 0; i < parameters.Count; ++i) {
3292 Parameter p = parameters [i];
3294 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3295 p.Warning_UselessOptionalParameter (Report);
3297 if (p.CheckAccessibility (this))
3300 TypeSpec t = parameters.Types [i];
3301 Report.SymbolRelatedToPreviousError (t);
3302 if (this is Indexer)
3303 Report.Error (55, Location,
3304 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3305 TypeManager.CSharpName (t), GetSignatureForError ());
3306 else if (this is Operator)
3307 Report.Error (57, Location,
3308 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3309 TypeManager.CSharpName (t), GetSignatureForError ());
3311 Report.Error (51, Location,
3312 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3313 TypeManager.CSharpName (t), GetSignatureForError ());
3319 protected override void DoMemberTypeDependentChecks ()
3321 base.DoMemberTypeDependentChecks ();
3323 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3326 public override void Emit()
3328 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3329 // We are more strict than csc and report this as an error because SRE does not allow emit that
3330 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3331 if (this is Constructor) {
3332 Report.Warning (824, 1, Location,
3333 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3335 Report.Warning (626, 1, Location,
3336 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3337 GetSignatureForError ());
3344 public override bool EnableOverloadChecks (MemberCore overload)
3347 // Two members can differ in their explicit interface
3348 // type parameter only
3350 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3351 if (imb != null && imb.IsExplicitImpl) {
3352 if (IsExplicitImpl) {
3353 caching_flags |= Flags.MethodOverloadsExist;
3358 return IsExplicitImpl;
3361 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3363 var base_modifiers = base_member.Modifiers;
3365 // Remove internal modifier from types which are not internally accessible
3366 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3367 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3368 base_modifiers = Modifiers.PROTECTED;
3370 Report.SymbolRelatedToPreviousError (base_member);
3371 Report.Error (507, member.Location,
3372 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3373 member.GetSignatureForError (),
3374 ModifiersExtensions.AccessibilityName (base_modifiers),
3375 base_member.GetSignatureForError ());
3378 protected void Error_StaticReturnType ()
3380 Report.Error (722, Location,
3381 "`{0}': static types cannot be used as return types",
3382 MemberType.GetSignatureForError ());
3386 /// Gets base method and its return type
3388 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3390 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3394 // The "short" name of this property / indexer / event. This is the
3395 // name without the explicit interface.
3397 public string ShortName {
3398 get { return MemberName.Name; }
3402 // Returns full metadata method name
3404 public string GetFullName (MemberName name)
3406 return GetFullName (name.Name);
3409 public string GetFullName (string name)
3411 if (!IsExplicitImpl)
3415 // When dealing with explicit members a full interface type
3416 // name is added to member name to avoid possible name conflicts
3418 // We use CSharpName which gets us full name with benefit of
3419 // replacing predefined names which saves some space and name
3422 return TypeManager.CSharpName (InterfaceType) + "." + name;
3425 public override string GetSignatureForDocumentation ()
3428 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3430 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3433 public override bool IsUsed
3435 get { return IsExplicitImpl || base.IsUsed; }
3438 public override void SetConstraints (List<Constraints> constraints_list)
3440 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3441 Report.Error (460, Location,
3442 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3443 GetSignatureForError ());
3446 base.SetConstraints (constraints_list);
3450 public abstract class MemberBase : MemberCore
3452 protected FullNamedExpression type_expr;
3453 protected TypeSpec member_type;
3454 public new TypeDefinition Parent;
3456 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3457 : base (parent, name, attrs)
3459 this.Parent = parent;
3460 this.type_expr = type;
3461 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3466 public TypeSpec MemberType {
3472 public FullNamedExpression TypeExpression {
3481 // Main member define entry
3483 public override bool Define ()
3485 DoMemberTypeIndependentChecks ();
3488 // Returns false only when type resolution failed
3490 if (!ResolveMemberType ())
3493 DoMemberTypeDependentChecks ();
3498 // Any type_name independent checks
3500 protected virtual void DoMemberTypeIndependentChecks ()
3502 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3503 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3504 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3505 GetSignatureForError (), Parent.GetSignatureForError ());
3510 // Any type_name dependent checks
3512 protected virtual void DoMemberTypeDependentChecks ()
3514 // verify accessibility
3515 if (!IsAccessibleAs (MemberType)) {
3516 Report.SymbolRelatedToPreviousError (MemberType);
3517 if (this is Property)
3518 Report.Error (53, Location,
3519 "Inconsistent accessibility: property type `" +
3520 TypeManager.CSharpName (MemberType) + "' is less " +
3521 "accessible than property `" + GetSignatureForError () + "'");
3522 else if (this is Indexer)
3523 Report.Error (54, Location,
3524 "Inconsistent accessibility: indexer return type `" +
3525 TypeManager.CSharpName (MemberType) + "' is less " +
3526 "accessible than indexer `" + GetSignatureForError () + "'");
3527 else if (this is MethodCore) {
3528 if (this is Operator)
3529 Report.Error (56, Location,
3530 "Inconsistent accessibility: return type `" +
3531 TypeManager.CSharpName (MemberType) + "' is less " +
3532 "accessible than operator `" + GetSignatureForError () + "'");
3534 Report.Error (50, Location,
3535 "Inconsistent accessibility: return type `" +
3536 TypeManager.CSharpName (MemberType) + "' is less " +
3537 "accessible than method `" + GetSignatureForError () + "'");
3539 Report.Error (52, Location,
3540 "Inconsistent accessibility: field type `" +
3541 TypeManager.CSharpName (MemberType) + "' is less " +
3542 "accessible than field `" + GetSignatureForError () + "'");
3547 protected void IsTypePermitted ()
3549 if (MemberType.IsSpecialRuntimeType) {
3550 if (Parent is StateMachine) {
3551 Report.Error (4012, Location,
3552 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3553 MemberType.GetSignatureForError ());
3554 } else if (Parent is HoistedStoreyClass) {
3555 Report.Error (4013, Location,
3556 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3557 MemberType.GetSignatureForError ());
3559 Report.Error (610, Location,
3560 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3565 protected virtual bool CheckBase ()
3567 CheckProtectedModifier ();
3572 public override string GetSignatureForDocumentation ()
3574 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3577 protected virtual bool ResolveMemberType ()
3579 if (member_type != null)
3580 throw new InternalErrorException ("Multi-resolve");
3582 member_type = type_expr.ResolveAsType (this);
3583 return member_type != null;