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)
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Security;
20 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;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public int CounterAnonymousMethods { get; set; }
57 public int CounterAnonymousContainers { get; set; }
58 public int CounterSwitchTypes { get; set; }
60 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
61 : base (parent, name, attrs)
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. Used
98 public Attributes UnattachedAttributes {
102 public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
104 AddTypeContainerMember (c);
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.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_MODIFIER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 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_MODIFIER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | 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 existing.AddPartialPart (next_part);
193 AddTypeContainerMember (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
198 AddTypeContainerMember (tc);
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 protected virtual void AddTypeContainerMember (TypeContainer tc)
218 public virtual void CloseContainer ()
220 if (containers != null) {
221 foreach (TypeContainer tc in containers) {
222 tc.CloseContainer ();
227 public virtual void CreateMetadataName (StringBuilder sb)
229 if (Parent != null && Parent.MemberName != null)
230 Parent.CreateMetadataName (sb);
232 MemberName.CreateMetadataName (sb);
235 public virtual bool CreateContainer ()
237 if (containers != null) {
238 foreach (TypeContainer tc in containers) {
239 tc.CreateContainer ();
246 public override bool Define ()
248 if (containers != null) {
249 foreach (TypeContainer tc in containers) {
254 // Release cache used by parser only
255 if (Module.Evaluator == null) {
256 defined_names = null;
258 defined_names.Clear ();
264 public virtual void PrepareEmit ()
266 if (containers != null) {
267 foreach (var t in containers) {
270 } catch (Exception e) {
271 if (MemberName == MemberName.Null)
274 throw new InternalErrorException (t, e);
280 public virtual bool DefineContainer ()
287 DoDefineContainer ();
289 if (containers != null) {
290 foreach (TypeContainer tc in containers) {
292 tc.DefineContainer ();
293 } catch (Exception e) {
294 if (MemberName == MemberName.Null)
297 throw new InternalErrorException (tc, e);
305 public virtual void ExpandBaseInterfaces ()
307 if (containers != null) {
308 foreach (TypeContainer tc in containers) {
309 tc.ExpandBaseInterfaces ();
314 protected virtual void DefineNamespace ()
316 if (containers != null) {
317 foreach (var tc in containers) {
319 tc.DefineNamespace ();
320 } catch (Exception e) {
321 throw new InternalErrorException (tc, e);
327 protected virtual void DoDefineContainer ()
331 public virtual void EmitContainer ()
333 if (containers != null) {
334 for (int i = 0; i < containers.Count; ++i)
335 containers[i].EmitContainer ();
339 protected void Error_MissingPartialModifier (MemberCore type)
341 Report.Error (260, type.Location,
342 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
343 type.GetSignatureForError ());
346 public override string GetSignatureForDocumentation ()
348 if (Parent != null && Parent.MemberName != null)
349 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
351 return MemberName.GetSignatureForDocumentation ();
354 public override string GetSignatureForError ()
356 if (Parent != null && Parent.MemberName != null)
357 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
359 return MemberName.GetSignatureForError ();
362 public virtual string GetSignatureForMetadata ()
364 var sb = new StringBuilder ();
365 CreateMetadataName (sb);
366 return sb.ToString ();
369 public virtual void RemoveContainer (TypeContainer cont)
371 if (containers != null)
372 containers.Remove (cont);
374 var tc = Parent == Module ? Module : this;
375 tc.defined_names.Remove (cont.MemberName.Basename);
378 public virtual void VerifyMembers ()
380 if (containers != null) {
381 foreach (TypeContainer tc in containers)
386 public override void WriteDebugSymbol (MonoSymbolFile file)
388 if (containers != null) {
389 foreach (TypeContainer tc in containers) {
390 tc.WriteDebugSymbol (file);
396 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
399 // Different context is needed when resolving type container base
400 // types. Type names come from the parent scope but type parameter
401 // names from the container scope.
403 public struct BaseContext : IMemberContext
407 public BaseContext (TypeContainer tc)
412 #region IMemberContext Members
414 public CompilerContext Compiler {
415 get { return tc.Compiler; }
418 public TypeSpec CurrentType {
419 get { return tc.PartialContainer.CurrentType; }
422 public TypeParameters CurrentTypeParameters {
423 get { return tc.PartialContainer.CurrentTypeParameters; }
426 public MemberCore CurrentMemberDefinition {
430 public bool IsObsolete {
431 get { return tc.IsObsolete; }
434 public bool IsUnsafe {
435 get { return tc.IsUnsafe; }
438 public bool IsStatic {
439 get { return tc.IsStatic; }
442 public ModuleContainer Module {
443 get { return tc.Module; }
446 public string GetSignatureForError ()
448 return tc.GetSignatureForError ();
451 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
456 public FullNamedExpression LookupNamespaceAlias (string name)
458 return tc.Parent.LookupNamespaceAlias (name);
461 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
464 var tp = CurrentTypeParameters;
466 TypeParameter t = tp.Find (name);
468 return new TypeParameterExpr (t, loc);
472 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
482 GetHashCode = 1 << 1,
483 HasStaticFieldInitializer = 1 << 2
486 readonly List<MemberCore> members;
488 // Holds a list of fields that have initializers
489 protected List<FieldInitializer> initialized_fields;
491 // Holds a list of static fields that have initializers
492 protected List<FieldInitializer> initialized_static_fields;
494 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
496 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
499 // Points to the first non-static field added to the container.
501 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
502 // and the first one's as good as any.
504 protected FieldBase first_nonstatic_field;
507 // This one is computed after we can distinguish interfaces
508 // from classes from the arraylist `type_bases'
510 protected TypeSpec base_type;
511 FullNamedExpression base_type_expr; // TODO: It's temporary variable
512 protected TypeSpec[] iface_exprs;
514 protected List<FullNamedExpression> type_bases;
516 // Partial parts for classes only
517 List<TypeDefinition> class_partial_parts;
519 TypeDefinition InTransit;
521 public TypeBuilder TypeBuilder;
522 GenericTypeParameterBuilder[] all_tp_builders;
524 // All recursive type parameters put together sharing same
525 // TypeParameter instances
527 TypeParameters all_type_parameters;
529 public const string DefaultIndexerName = "Item";
531 bool has_normal_indexers;
534 bool members_defined;
535 bool members_defined_ok;
536 protected bool has_static_constructor;
538 private CachedMethods cached_method;
540 protected TypeSpec spec;
541 TypeSpec current_type;
543 public int DynamicSitesCounter;
544 public int AnonymousMethodsCounter;
545 public int MethodGroupsCounter;
547 static readonly string[] attribute_targets = new [] { "type" };
548 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
551 /// The pending methods that need to be implemented
552 // (interfaces or abstract methods)
554 PendingImplementation pending;
556 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
557 : base (parent, name, attrs, kind)
559 PartialContainer = this;
560 members = new List<MemberCore> ();
565 public List<FullNamedExpression> BaseTypeExpressions {
571 public override TypeSpec CurrentType {
573 if (current_type == null) {
574 if (IsGenericOrParentIsGeneric) {
576 // Switch to inflated version as it's used by all expressions
578 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
579 current_type = spec.MakeGenericType (this, targs);
589 public override TypeParameters CurrentTypeParameters {
591 return PartialContainer.MemberName.TypeParameters;
595 int CurrentTypeParametersStartIndex {
597 int total = all_tp_builders.Length;
598 if (CurrentTypeParameters != null) {
599 return total - CurrentTypeParameters.Count;
605 public virtual AssemblyDefinition DeclaringAssembly {
607 return Module.DeclaringAssembly;
611 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
613 return Module.DeclaringAssembly;
617 public TypeSpec Definition {
623 public bool HasMembersDefined {
625 return members_defined;
629 public bool HasInstanceConstructor {
631 return (caching_flags & Flags.HasInstanceConstructor) != 0;
634 caching_flags |= Flags.HasInstanceConstructor;
638 // Indicated whether container has StructLayout attribute set Explicit
639 public bool HasExplicitLayout {
640 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
641 set { caching_flags |= Flags.HasExplicitLayout; }
644 public bool HasOperators {
646 return (caching_flags & Flags.HasUserOperators) != 0;
649 caching_flags |= Flags.HasUserOperators;
653 public bool HasStructLayout {
654 get { return (caching_flags & Flags.HasStructLayout) != 0; }
655 set { caching_flags |= Flags.HasStructLayout; }
658 public TypeSpec[] Interfaces {
664 public bool IsGenericOrParentIsGeneric {
666 return all_type_parameters != null;
670 public bool IsTopLevel {
672 return !(Parent is TypeDefinition);
676 public bool IsPartial {
678 return (ModFlags & Modifiers.PARTIAL) != 0;
682 bool ITypeDefinition.IsTypeForwarder {
688 bool ITypeDefinition.IsCyclicTypeForwarder {
695 // Returns true for secondary partial containers
699 return PartialContainer != this;
703 public MemberCache MemberCache {
705 return spec.MemberCache;
709 public List<MemberCore> Members {
715 string ITypeDefinition.Namespace {
718 while (p.Kind != MemberKind.Namespace)
721 return p.MemberName == null ? null : p.GetSignatureForError ();
725 public ParametersCompiled PrimaryConstructorParameters { get; set; }
727 public Arguments PrimaryConstructorBaseArguments { get; set; }
729 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
731 public TypeParameters TypeParametersAll {
733 return all_type_parameters;
737 public override string[] ValidAttributeTargets {
739 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
745 public override void Accept (StructuralVisitor visitor)
747 visitor.Visit (this);
750 public void AddMember (MemberCore symbol)
752 if (symbol.MemberName.ExplicitInterface != null) {
753 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
754 Report.Error (541, symbol.Location,
755 "`{0}': explicit interface declaration can only be declared in a class or struct",
756 symbol.GetSignatureForError ());
760 AddNameToContainer (symbol, symbol.MemberName.Name);
761 members.Add (symbol);
764 public override void AddTypeContainer (TypeContainer tc)
766 AddNameToContainer (tc, tc.MemberName.Basename);
768 base.AddTypeContainer (tc);
771 protected override void AddTypeContainerMember (TypeContainer tc)
775 if (containers == null)
776 containers = new List<TypeContainer> ();
778 base.AddTypeContainerMember (tc);
782 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
784 public virtual void AddNameToContainer (MemberCore symbol, string name)
786 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
790 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
791 PartialContainer.defined_names.Add (name, symbol);
795 if (symbol.EnableOverloadChecks (mc))
798 InterfaceMemberBase im = mc as InterfaceMemberBase;
799 if (im != null && im.IsExplicitImpl)
802 Report.SymbolRelatedToPreviousError (mc);
803 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
804 Error_MissingPartialModifier (symbol);
808 if (symbol is TypeParameter) {
809 Report.Error (692, symbol.Location,
810 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
812 Report.Error (102, symbol.Location,
813 "The type `{0}' already contains a definition for `{1}'",
814 GetSignatureForError (), name);
820 public void AddConstructor (Constructor c)
822 AddConstructor (c, false);
825 public void AddConstructor (Constructor c, bool isDefault)
827 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
829 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
831 if (is_static && c.ParameterInfo.IsEmpty) {
832 PartialContainer.has_static_constructor = true;
834 PartialContainer.HasInstanceConstructor = true;
840 public bool AddField (FieldBase field)
844 if ((field.ModFlags & Modifiers.STATIC) != 0)
847 var first_field = PartialContainer.first_nonstatic_field;
848 if (first_field == null) {
849 PartialContainer.first_nonstatic_field = field;
853 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
854 Report.SymbolRelatedToPreviousError (first_field.Parent);
855 Report.Warning (282, 3, field.Location,
856 "struct instance field `{0}' found in different declaration from instance field `{1}'",
857 field.GetSignatureForError (), first_field.GetSignatureForError ());
863 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
865 public void AddIndexer (Indexer i)
870 public void AddOperator (Operator op)
872 PartialContainer.HasOperators = true;
876 public void AddPartialPart (TypeDefinition part)
878 if (Kind != MemberKind.Class)
881 if (class_partial_parts == null)
882 class_partial_parts = new List<TypeDefinition> ();
884 class_partial_parts.Add (part);
887 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
889 if (a.Target == AttributeTargets.Method) {
890 foreach (var m in members) {
891 var c = m as Constructor;
895 if (c.IsPrimaryConstructor) {
896 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
901 throw new InternalErrorException ();
904 if (has_normal_indexers && a.Type == pa.DefaultMember) {
905 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
909 if (a.Type == pa.Required) {
910 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
914 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
917 public override AttributeTargets AttributeTargets {
919 throw new NotSupportedException ();
923 public TypeSpec BaseType {
925 return spec.BaseType;
929 protected virtual TypeAttributes TypeAttr {
931 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
935 public int TypeParametersCount {
937 return MemberName.Arity;
941 TypeParameterSpec[] ITypeDefinition.TypeParameters {
943 return PartialContainer.CurrentTypeParameters.Types;
947 public string GetAttributeDefaultMember ()
949 return indexer_name ?? DefaultIndexerName;
952 public bool IsComImport {
954 if (OptAttributes == null)
957 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
961 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
964 PartialContainer.RegisterFieldForInitialization (field, expression);
966 if ((field.ModFlags & Modifiers.STATIC) != 0){
967 if (initialized_static_fields == null) {
968 HasStaticFieldInitializer = true;
969 initialized_static_fields = new List<FieldInitializer> (4);
972 initialized_static_fields.Add (expression);
974 if (Kind == MemberKind.Struct) {
975 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
976 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
977 GetSignatureForError ());
981 if (initialized_fields == null)
982 initialized_fields = new List<FieldInitializer> (4);
984 initialized_fields.Add (expression);
988 public void ResolveFieldInitializers (BlockContext ec)
990 Debug.Assert (!IsPartialPart);
993 if (initialized_static_fields == null)
996 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
998 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
999 for (i = 0; i < initialized_static_fields.Count; ++i) {
1000 FieldInitializer fi = initialized_static_fields [i];
1001 ExpressionStatement s = fi.ResolveStatement (ec);
1003 s = EmptyExpressionStatement.Instance;
1004 } else if (!fi.IsSideEffectFree) {
1005 has_complex_initializer = true;
1011 for (i = 0; i < initialized_static_fields.Count; ++i) {
1012 FieldInitializer fi = initialized_static_fields [i];
1014 // Need special check to not optimize code like this
1015 // static int a = b = 5;
1016 // static int b = 0;
1018 if (!has_complex_initializer && fi.IsDefaultInitializer)
1021 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1022 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1028 if (initialized_fields == null)
1031 for (int i = 0; i < initialized_fields.Count; ++i) {
1032 FieldInitializer fi = initialized_fields [i];
1035 // Clone before resolving otherwise when field initializer is needed
1036 // in more than 1 constructor any resolve after the initial one would
1037 // only took the resolved expression which is problem for expressions
1038 // that generate extra expressions or code during Resolve phase
1040 var cloned = fi.Clone (new CloneContext ());
1042 ExpressionStatement s = fi.ResolveStatement (ec);
1044 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1049 // Field is re-initialized to its default value => removed
1051 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1054 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1055 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1056 initialized_fields [i] = (FieldInitializer) cloned;
1060 public override string DocComment {
1072 public PendingImplementation PendingImplementations {
1073 get { return pending; }
1076 internal override void GenerateDocComment (DocumentationBuilder builder)
1081 base.GenerateDocComment (builder);
1083 foreach (var member in members)
1084 member.GenerateDocComment (builder);
1087 public TypeSpec GetAttributeCoClass ()
1089 if (OptAttributes == null)
1092 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1096 return a.GetCoClassAttributeValue ();
1099 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1102 if (OptAttributes != null) {
1103 a = OptAttributes.Search (pa);
1109 return a.GetAttributeUsageAttribute ();
1112 public virtual CompilationSourceFile GetCompilationSourceFile ()
1114 TypeContainer ns = Parent;
1116 var sf = ns as CompilationSourceFile;
1124 public override string GetSignatureForMetadata ()
1126 if (Parent is TypeDefinition) {
1127 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1130 return base.GetSignatureForMetadata ();
1133 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1135 type_bases = baseTypes;
1139 /// This function computes the Base class and also the
1140 /// list of interfaces that the class or struct @c implements.
1142 /// The return value is an array (might be null) of
1143 /// interfaces implemented (as Types).
1145 /// The @base_class argument is set to the base object or null
1146 /// if this is `System.Object'.
1148 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1151 if (type_bases == null)
1154 int count = type_bases.Count;
1155 TypeSpec[] ifaces = null;
1156 var base_context = new BaseContext (this);
1157 for (int i = 0, j = 0; i < count; i++){
1158 FullNamedExpression fne = type_bases [i];
1160 var fne_resolved = fne.ResolveAsType (base_context);
1161 if (fne_resolved == null)
1164 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1165 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1166 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1167 GetSignatureForError ());
1172 base_type = fne_resolved;
1178 ifaces = new TypeSpec [count - i];
1180 if (fne_resolved.IsInterface) {
1181 for (int ii = 0; ii < j; ++ii) {
1182 if (fne_resolved == ifaces [ii]) {
1183 Report.Error (528, Location, "`{0}' is already listed in interface list",
1184 fne_resolved.GetSignatureForError ());
1189 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1190 Report.Error (61, fne.Location,
1191 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1192 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1195 Report.SymbolRelatedToPreviousError (fne_resolved);
1196 if (Kind != MemberKind.Class) {
1197 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1198 } else if (base_class != null)
1199 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1200 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1202 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1203 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1207 ifaces [j++] = fne_resolved;
1214 // Checks that some operators come in pairs:
1220 // They are matched based on the return type and the argument types
1222 void CheckPairedOperators ()
1224 bool has_equality_or_inequality = false;
1225 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1227 for (int i = 0; i < members.Count; ++i) {
1228 var o_a = members[i] as Operator;
1232 var o_type = o_a.OperatorType;
1233 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1234 has_equality_or_inequality = true;
1236 if (found_matched.Contains (o_type))
1239 var matching_type = o_a.GetMatchingOperator ();
1240 if (matching_type == Operator.OpType.TOP) {
1244 bool pair_found = false;
1245 for (int ii = 0; ii < members.Count; ++ii) {
1246 var o_b = members[ii] as Operator;
1247 if (o_b == null || o_b.OperatorType != matching_type)
1250 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1253 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1256 found_matched.Add (matching_type);
1262 Report.Error (216, o_a.Location,
1263 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1264 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1268 if (has_equality_or_inequality) {
1270 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1271 GetSignatureForError ());
1273 if (!HasGetHashCode)
1274 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1275 GetSignatureForError ());
1279 public override void CreateMetadataName (StringBuilder sb)
1281 if (Parent.MemberName != null) {
1282 Parent.CreateMetadataName (sb);
1284 if (sb.Length != 0) {
1289 sb.Append (MemberName.Basename);
1292 bool CreateTypeBuilder ()
1295 // Sets .size to 1 for structs with no instance fields
1297 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1299 var parent_def = Parent as TypeDefinition;
1300 if (parent_def == null) {
1301 var sb = new StringBuilder ();
1302 CreateMetadataName (sb);
1303 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1305 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1308 if (DeclaringAssembly.Importer != null)
1309 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1311 spec.SetMetaInfo (TypeBuilder);
1312 spec.MemberCache = new MemberCache (this);
1314 TypeParameters parentAllTypeParameters = null;
1315 if (parent_def != null) {
1316 spec.DeclaringType = Parent.CurrentType;
1317 parent_def.MemberCache.AddMember (spec);
1318 parentAllTypeParameters = parent_def.all_type_parameters;
1321 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1322 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1324 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1326 if (CurrentTypeParameters != null) {
1327 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1328 CurrentTypeParameters.Define (all_tp_builders);
1335 public static string FilterNestedName (string name)
1338 // SRE API does not handle namespaces and types separately but
1339 // determine that from '.' in name. That's problematic because
1340 // dot is valid character for type name. By replacing any '.'
1341 // in name we avoid any ambiguities and never emit metadata
1342 // namespace for nested types
1344 return name.Replace ('.', '_');
1347 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1350 int parent_offset = 0;
1351 if (parentAllTypeParameters != null) {
1352 if (CurrentTypeParameters == null) {
1353 all_type_parameters = parentAllTypeParameters;
1354 return parentAllTypeParameters.GetAllNames ();
1357 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1358 all_type_parameters = new TypeParameters (names.Length);
1359 all_type_parameters.Add (parentAllTypeParameters);
1361 parent_offset = all_type_parameters.Count;
1362 for (int i = 0; i < parent_offset; ++i)
1363 names[i] = all_type_parameters[i].MemberName.Name;
1366 names = new string[CurrentTypeParameters.Count];
1369 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1370 if (all_type_parameters != null)
1371 all_type_parameters.Add (MemberName.TypeParameters[i]);
1373 var name = CurrentTypeParameters[i].MemberName.Name;
1374 names[parent_offset + i] = name;
1375 for (int ii = 0; ii < parent_offset + i; ++ii) {
1376 if (names[ii] != name)
1379 var tp = CurrentTypeParameters[i];
1380 var conflict = all_type_parameters[ii];
1382 tp.WarningParentNameConflict (conflict);
1386 if (all_type_parameters == null)
1387 all_type_parameters = CurrentTypeParameters;
1393 public SourceMethodBuilder CreateMethodSymbolEntry ()
1395 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1398 var source_file = GetCompilationSourceFile ();
1399 if (source_file == null)
1402 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1406 // Creates a proxy base method call inside this container for hoisted base member calls
1408 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1410 Method proxy_method;
1413 // One proxy per base method is enough
1415 if (hoisted_base_call_proxies == null) {
1416 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1417 proxy_method = null;
1419 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1422 if (proxy_method == null) {
1423 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1425 MemberName member_name;
1426 TypeArguments targs = null;
1427 TypeSpec return_type = method.ReturnType;
1428 var local_param_types = method.Parameters.Types;
1430 if (method.IsGeneric) {
1432 // Copy all base generic method type parameters info
1434 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1435 var tparams = new TypeParameters ();
1437 targs = new TypeArguments ();
1438 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1439 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1440 var tp = hoisted_tparams[i];
1441 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1442 tparams.Add (local_tp);
1444 targs.Add (new SimpleName (tp.Name, Location));
1445 targs.Arguments[i] = local_tp.Type;
1448 member_name = new MemberName (name, tparams, Location);
1451 // Mutate any method type parameters from original
1452 // to newly created hoisted version
1454 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1455 return_type = mutator.Mutate (return_type);
1456 local_param_types = mutator.Mutate (local_param_types);
1458 member_name = new MemberName (name);
1461 var base_parameters = new Parameter[method.Parameters.Count];
1462 for (int i = 0; i < base_parameters.Length; ++i) {
1463 var base_param = method.Parameters.FixedParameters[i];
1464 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1465 base_param.Name, base_param.ModFlags, null, Location);
1466 base_parameters[i].Resolve (this, i);
1469 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1470 if (method.Parameters.HasArglist) {
1471 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1472 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1475 // Compiler generated proxy
1476 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1477 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1478 member_name, cloned_params, null);
1480 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1481 IsCompilerGenerated = true
1484 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1485 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1487 mg.SetTypeArguments (rc, targs);
1489 // Get all the method parameters and pass them as arguments
1490 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1491 Statement statement;
1492 if (method.ReturnType.Kind == MemberKind.Void)
1493 statement = new StatementExpression (real_base_call);
1495 statement = new Return (real_base_call, Location);
1497 block.AddStatement (statement);
1498 proxy_method.Block = block;
1500 members.Add (proxy_method);
1501 proxy_method.Define ();
1502 proxy_method.PrepareEmit ();
1504 hoisted_base_call_proxies.Add (method, proxy_method);
1507 return proxy_method.Spec;
1510 protected bool DefineBaseTypes ()
1512 if (IsPartialPart && Kind == MemberKind.Class)
1515 return DoDefineBaseType ();
1518 bool DoDefineBaseType ()
1520 iface_exprs = ResolveBaseTypes (out base_type_expr);
1523 if (IsPartialPart) {
1524 set_base_type = false;
1526 if (base_type_expr != null) {
1527 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1528 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1529 Report.Error (263, Location,
1530 "Partial declarations of `{0}' must not specify different base classes",
1531 GetSignatureForError ());
1533 PartialContainer.base_type_expr = base_type_expr;
1534 PartialContainer.base_type = base_type;
1535 set_base_type = true;
1539 if (iface_exprs != null) {
1540 if (PartialContainer.iface_exprs == null)
1541 PartialContainer.iface_exprs = iface_exprs;
1543 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1544 foreach (var iface_partial in iface_exprs) {
1545 if (ifaces.Contains (iface_partial))
1548 ifaces.Add (iface_partial);
1551 PartialContainer.iface_exprs = ifaces.ToArray ();
1555 PartialContainer.members.AddRange (members);
1556 if (containers != null) {
1557 if (PartialContainer.containers == null)
1558 PartialContainer.containers = new List<TypeContainer> ();
1560 PartialContainer.containers.AddRange (containers);
1563 if (PrimaryConstructorParameters != null) {
1564 if (PartialContainer.PrimaryConstructorParameters != null) {
1565 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1567 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1571 members_defined = members_defined_ok = true;
1572 caching_flags |= Flags.CloseTypeCreated;
1574 set_base_type = true;
1577 var cycle = CheckRecursiveDefinition (this);
1578 if (cycle != null) {
1579 Report.SymbolRelatedToPreviousError (cycle);
1580 if (this is Interface) {
1581 Report.Error (529, Location,
1582 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1583 GetSignatureForError (), cycle.GetSignatureForError ());
1586 PartialContainer.iface_exprs = null;
1588 Report.Error (146, Location,
1589 "Circular base class dependency involving `{0}' and `{1}'",
1590 GetSignatureForError (), cycle.GetSignatureForError ());
1593 PartialContainer.base_type = null;
1597 if (iface_exprs != null) {
1598 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1599 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1602 foreach (var iface_type in iface_exprs) {
1603 // Prevents a crash, the interface might not have been resolved: 442144
1604 if (iface_type == null)
1607 if (!spec.AddInterfaceDefined (iface_type))
1610 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1614 if (Kind == MemberKind.Interface) {
1615 spec.BaseType = Compiler.BuiltinTypes.Object;
1619 if (set_base_type) {
1624 // Base type of partial container has to be resolved before we
1625 // resolve any nested types of the container. We need to know
1626 // partial parts because the base type can be specified in file
1627 // defined after current container
1629 if (class_partial_parts != null) {
1630 foreach (var pp in class_partial_parts) {
1631 if (pp.PrimaryConstructorBaseArguments != null)
1632 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1634 pp.DoDefineBaseType ();
1644 if (base_type == null) {
1645 TypeBuilder.SetParent (null);
1649 if (spec.BaseType == base_type)
1652 spec.BaseType = base_type;
1655 spec.UpdateInflatedInstancesBaseType ();
1657 // Set base type after type creation
1658 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1661 public override void ExpandBaseInterfaces ()
1664 DoExpandBaseInterfaces ();
1666 base.ExpandBaseInterfaces ();
1669 public void DoExpandBaseInterfaces ()
1671 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1674 caching_flags |= Flags.InterfacesExpanded;
1677 // Expand base interfaces. It cannot be done earlier because all partial
1678 // interface parts need to be defined before the type they are used from
1680 if (iface_exprs != null) {
1681 foreach (var iface in iface_exprs) {
1685 var td = iface.MemberDefinition as TypeDefinition;
1687 td.DoExpandBaseInterfaces ();
1689 if (iface.Interfaces == null)
1692 foreach (var biface in iface.Interfaces) {
1693 if (spec.AddInterfaceDefined (biface)) {
1694 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1701 // Include all base type interfaces too, see ImportTypeBase for details
1703 if (base_type != null) {
1704 var td = base_type.MemberDefinition as TypeDefinition;
1706 td.DoExpandBaseInterfaces ();
1709 // Simply use base interfaces only, they are all expanded which makes
1710 // it easy to handle generic type argument propagation with single
1713 // interface IA<T> : IB<T>
1714 // interface IB<U> : IC<U>
1717 if (base_type.Interfaces != null) {
1718 foreach (var iface in base_type.Interfaces) {
1719 spec.AddInterfaceDefined (iface);
1725 public override void PrepareEmit ()
1727 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1730 foreach (var member in members) {
1731 var pbm = member as MemberBase;
1736 base.PrepareEmit ();
1740 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1742 public override bool CreateContainer ()
1744 if (TypeBuilder != null)
1750 if (IsPartialPart) {
1751 spec = PartialContainer.spec;
1752 TypeBuilder = PartialContainer.TypeBuilder;
1753 all_tp_builders = PartialContainer.all_tp_builders;
1754 all_type_parameters = PartialContainer.all_type_parameters;
1756 if (!CreateTypeBuilder ()) {
1762 return base.CreateContainer ();
1765 protected override void DoDefineContainer ()
1769 DoResolveTypeParameters ();
1773 // Replaces normal spec with predefined one when compiling corlib
1774 // and this type container defines predefined type
1776 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1778 // When compiling build-in types we start with two
1779 // version of same type. One is of BuiltinTypeSpec and
1780 // second one is ordinary TypeSpec. The unification
1781 // happens at later stage when we know which type
1782 // really matches the builtin type signature. However
1783 // that means TypeSpec create during CreateType of this
1784 // type has to be replaced with builtin one
1786 spec.SetMetaInfo (TypeBuilder);
1787 spec.MemberCache = this.spec.MemberCache;
1788 spec.DeclaringType = this.spec.DeclaringType;
1791 current_type = null;
1792 if (class_partial_parts != null) {
1793 foreach (var part in class_partial_parts)
1798 public override void RemoveContainer (TypeContainer cont)
1800 base.RemoveContainer (cont);
1801 Members.Remove (cont);
1802 Cache.Remove (cont.MemberName.Basename);
1805 protected virtual bool DoResolveTypeParameters ()
1807 var tparams = MemberName.TypeParameters;
1808 if (tparams == null)
1811 var base_context = new BaseContext (this);
1812 for (int i = 0; i < tparams.Count; ++i) {
1813 var tp = tparams[i];
1815 if (!tp.ResolveConstraints (base_context)) {
1820 if (IsPartialPart) {
1821 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1823 tp.Create (spec, this);
1826 if (tp.OptAttributes != null) {
1827 if (pc_tp.OptAttributes == null)
1828 pc_tp.OptAttributes = tp.OptAttributes;
1830 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1835 if (IsPartialPart) {
1836 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1842 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1844 if (InTransit != null)
1849 if (base_type != null) {
1850 var ptc = base_type.MemberDefinition as TypeDefinition;
1851 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1855 if (iface_exprs != null) {
1856 foreach (var iface in iface_exprs) {
1857 // the interface might not have been resolved, prevents a crash, see #442144
1860 var ptc = iface.MemberDefinition as Interface;
1861 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1866 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1874 /// Populates our TypeBuilder with fields and methods
1876 public sealed override bool Define ()
1878 if (members_defined)
1879 return members_defined_ok;
1881 members_defined_ok = DoDefineMembers ();
1882 members_defined = true;
1886 return members_defined_ok;
1889 protected virtual bool DoDefineMembers ()
1891 Debug.Assert (!IsPartialPart);
1893 if (iface_exprs != null) {
1894 foreach (var iface_type in iface_exprs) {
1895 if (iface_type == null)
1898 // Ensure the base is always setup
1899 var compiled_iface = iface_type.MemberDefinition as Interface;
1900 if (compiled_iface != null)
1901 compiled_iface.Define ();
1903 iface_type.CheckObsoleteness (this, Location);
1905 if (iface_type.Arity > 0) {
1906 // TODO: passing `this' is wrong, should be base type iface instead
1907 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1909 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1910 Report.Error (1966, Location,
1911 "`{0}': cannot implement a dynamic interface `{1}'",
1912 GetSignatureForError (), iface_type.GetSignatureForError ());
1917 if (iface_type.IsGenericOrParentIsGeneric) {
1918 foreach (var prev_iface in iface_exprs) {
1919 if (prev_iface == iface_type || prev_iface == null)
1922 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1925 Report.Error (695, Location,
1926 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1927 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1932 if (Kind == MemberKind.Interface) {
1933 foreach (var iface in spec.Interfaces) {
1934 MemberCache.AddInterface (iface);
1939 if (base_type != null) {
1941 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1943 if (base_type_expr != null) {
1944 base_type.CheckObsoleteness (this, base_type_expr.Location);
1946 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1947 Report.Error (698, base_type_expr.Location,
1948 "A generic type cannot derive from `{0}' because it is an attribute class",
1949 base_type.GetSignatureForError ());
1953 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1954 if (baseContainer != null) {
1955 baseContainer.Define ();
1958 // It can trigger define of this type (for generic types only)
1960 if (HasMembersDefined)
1965 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1966 pending = PendingImplementation.GetPendingImplementations (this);
1969 var count = members.Count;
1970 for (int i = 0; i < count; ++i) {
1971 var mc = members[i] as InterfaceMemberBase;
1972 if (mc == null || !mc.IsExplicitImpl)
1977 } catch (Exception e) {
1978 throw new InternalErrorException (mc, e);
1982 for (int i = 0; i < count; ++i) {
1983 var mc = members[i] as InterfaceMemberBase;
1984 if (mc != null && mc.IsExplicitImpl)
1987 if (members[i] is TypeContainer)
1991 members[i].Define ();
1992 } catch (Exception e) {
1993 throw new InternalErrorException (members[i], e);
1998 CheckPairedOperators ();
2001 ComputeIndexerName();
2003 if (HasEquals && !HasGetHashCode) {
2004 Report.Warning (659, 3, Location,
2005 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2008 if (Kind == MemberKind.Interface && iface_exprs != null) {
2009 MemberCache.RemoveHiddenMembers (spec);
2015 void ComputeIndexerName ()
2017 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2018 if (indexers == null)
2021 string class_indexer_name = null;
2024 // Check normal indexers for consistent name, explicit interface implementation
2025 // indexers are ignored
2027 foreach (var indexer in indexers) {
2029 // FindMembers can return unfiltered full hierarchy names
2031 if (indexer.DeclaringType != spec)
2034 has_normal_indexers = true;
2036 if (class_indexer_name == null) {
2037 indexer_name = class_indexer_name = indexer.Name;
2041 if (indexer.Name != class_indexer_name)
2042 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2043 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2047 void EmitIndexerName ()
2049 if (!has_normal_indexers)
2052 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2056 var encoder = new AttributeEncoder ();
2057 encoder.Encode (GetAttributeDefaultMember ());
2058 encoder.EncodeEmptyNamedArguments ();
2060 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2063 public override void VerifyMembers ()
2066 // Check for internal or private fields that were never assigned
2068 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2069 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2070 foreach (var member in members) {
2071 if (member is Event) {
2073 // An event can be assigned from same class only, report
2074 // this warning for all accessibility modes
2076 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2077 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2082 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2083 if (is_type_exposed)
2086 member.SetIsUsed ();
2089 var f = member as Field;
2093 if (!member.IsUsed) {
2094 if (!PartialContainer.HasStructLayout) {
2095 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2096 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2098 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2099 member.GetSignatureForError ());
2106 if ((f.caching_flags & Flags.IsAssigned) != 0)
2110 // Only report 649 on level 4
2112 if (Compiler.Settings.WarningLevel < 4)
2116 // Don't be pedantic when type requires specific layout
2118 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2121 Constant c = New.Constantify (f.MemberType, f.Location);
2124 value = c.GetValueAsLiteral ();
2125 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2132 value = " `" + value + "'";
2134 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2135 f.GetSignatureForError (), value);
2139 base.VerifyMembers ();
2142 public override void Emit ()
2144 if (OptAttributes != null)
2145 OptAttributes.Emit ();
2147 if (!IsCompilerGenerated) {
2149 MemberSpec candidate;
2150 bool overrides = false;
2151 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2152 if (conflict_symbol == null && candidate == null) {
2153 if ((ModFlags & Modifiers.NEW) != 0)
2154 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2155 GetSignatureForError ());
2157 if ((ModFlags & Modifiers.NEW) == 0) {
2158 if (candidate == null)
2159 candidate = conflict_symbol;
2161 Report.SymbolRelatedToPreviousError (candidate);
2162 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2163 GetSignatureForError (), candidate.GetSignatureForError ());
2168 // Run constraints check on all possible generic types
2169 if (base_type != null && base_type_expr != null) {
2170 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2173 if (iface_exprs != null) {
2174 foreach (var iface_type in iface_exprs) {
2175 if (iface_type == null)
2178 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2183 if (all_tp_builders != null) {
2184 int current_starts_index = CurrentTypeParametersStartIndex;
2185 for (int i = 0; i < all_tp_builders.Length; i++) {
2186 if (i < current_starts_index) {
2187 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2189 var tp = CurrentTypeParameters [i - current_starts_index];
2190 tp.CheckGenericConstraints (!IsObsolete);
2196 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2197 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2200 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2201 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2206 for (int i = 0; i < members.Count; i++) {
2208 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2215 CheckAttributeClsCompliance ();
2217 if (pending != null)
2218 pending.VerifyPendingMethods ();
2222 void CheckAttributeClsCompliance ()
2224 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2227 foreach (var m in members) {
2228 var c = m as Constructor;
2232 if (c.HasCompliantArgs)
2236 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2239 public sealed override void EmitContainer ()
2241 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2247 public override void CloseContainer ()
2249 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2252 // Close base type container first to avoid TypeLoadException
2253 if (spec.BaseType != null) {
2254 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2255 if (btype != null) {
2256 btype.CloseContainer ();
2258 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2264 caching_flags |= Flags.CloseTypeCreated;
2265 TypeBuilder.CreateType ();
2266 } catch (TypeLoadException) {
2268 // This is fine, the code still created the type
2270 } catch (Exception e) {
2271 throw new InternalErrorException (this, e);
2274 base.CloseContainer ();
2277 initialized_fields = null;
2278 initialized_static_fields = null;
2280 OptAttributes = null;
2284 // Performs the validation on a Method's modifiers (properties have
2285 // the same properties).
2287 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2289 public bool MethodModifiersValid (MemberCore mc)
2291 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2292 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2294 var flags = mc.ModFlags;
2297 // At most one of static, virtual or override
2299 if ((flags & Modifiers.STATIC) != 0){
2300 if ((flags & vao) != 0){
2301 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2302 mc.GetSignatureForError ());
2307 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2308 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2309 mc.GetSignatureForError ());
2314 // If the declaration includes the abstract modifier, then the
2315 // declaration does not include static, virtual or extern
2317 if ((flags & Modifiers.ABSTRACT) != 0){
2318 if ((flags & Modifiers.EXTERN) != 0){
2320 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2324 if ((flags & Modifiers.SEALED) != 0) {
2325 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2329 if ((flags & Modifiers.VIRTUAL) != 0){
2330 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2334 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2335 Report.SymbolRelatedToPreviousError (this);
2336 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2337 mc.GetSignatureForError (), GetSignatureForError ());
2342 if ((flags & Modifiers.PRIVATE) != 0){
2343 if ((flags & vao) != 0){
2344 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2349 if ((flags & Modifiers.SEALED) != 0){
2350 if ((flags & Modifiers.OVERRIDE) == 0){
2351 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2359 protected override bool VerifyClsCompliance ()
2361 if (!base.VerifyClsCompliance ())
2364 // Check all container names for user classes
2365 if (Kind != MemberKind.Delegate)
2366 MemberCache.VerifyClsCompliance (Definition, Report);
2368 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2369 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2370 GetSignatureForError (), BaseType.GetSignatureForError ());
2376 /// Performs checks for an explicit interface implementation. First it
2377 /// checks whether the `interface_type' is a base inteface implementation.
2378 /// Then it checks whether `name' exists in the interface type.
2380 public bool VerifyImplements (InterfaceMemberBase mb)
2382 var ifaces = PartialContainer.Interfaces;
2383 if (ifaces != null) {
2384 foreach (TypeSpec t in ifaces){
2385 if (t == mb.InterfaceType)
2388 var expanded_base = t.Interfaces;
2389 if (expanded_base == null)
2392 foreach (var bt in expanded_base) {
2393 if (bt == mb.InterfaceType)
2399 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2400 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2401 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2406 // Used for visiblity checks to tests whether this definition shares
2407 // base type baseType, it does member-definition search
2409 public bool IsBaseTypeDefinition (TypeSpec baseType)
2411 // RootContext check
2412 if (TypeBuilder == null)
2417 if (type.MemberDefinition == baseType.MemberDefinition)
2420 type = type.BaseType;
2421 } while (type != null);
2426 public override bool IsClsComplianceRequired ()
2429 return PartialContainer.IsClsComplianceRequired ();
2431 return base.IsClsComplianceRequired ();
2434 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2436 return Module.DeclaringAssembly == assembly;
2439 public virtual bool IsUnmanagedType ()
2444 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2446 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2450 // Public function used to locate types.
2452 // Returns: Type or null if they type can not be found.
2454 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2456 FullNamedExpression e;
2457 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2463 var tp = CurrentTypeParameters;
2465 TypeParameter tparam = tp.Find (name);
2467 e = new TypeParameterExpr (tparam, Location.Null);
2472 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2474 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2475 e = new TypeExpression (t, Location.Null);
2477 var errors = Compiler.Report.Errors;
2478 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2480 // TODO: LookupNamespaceOrType does more than just lookup. The result
2481 // cannot be cached or the error reporting won't happen
2482 if (errors != Compiler.Report.Errors)
2487 // TODO MemberCache: How to cache arity stuff ?
2488 if (arity == 0 && mode == LookupMode.Normal)
2494 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2496 // Has any nested type
2497 // Does not work, because base type can have
2498 //if (PartialContainer.Types == null)
2501 var container = PartialContainer.CurrentType;
2502 return MemberCache.FindNestedType (container, name, arity);
2505 public void Mark_HasEquals ()
2507 cached_method |= CachedMethods.Equals;
2510 public void Mark_HasGetHashCode ()
2512 cached_method |= CachedMethods.GetHashCode;
2515 public override void WriteDebugSymbol (MonoSymbolFile file)
2520 foreach (var m in members) {
2521 m.WriteDebugSymbol (file);
2526 /// Method container contains Equals method
2528 public bool HasEquals {
2530 return (cached_method & CachedMethods.Equals) != 0;
2535 /// Method container contains GetHashCode method
2537 public bool HasGetHashCode {
2539 return (cached_method & CachedMethods.GetHashCode) != 0;
2543 public bool HasStaticFieldInitializer {
2545 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2549 cached_method |= CachedMethods.HasStaticFieldInitializer;
2551 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2555 public override string DocCommentHeader {
2556 get { return "T:"; }
2560 public abstract class ClassOrStruct : TypeDefinition
2562 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2564 SecurityType declarative_security;
2565 protected Constructor generated_primary_constructor;
2567 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2568 : base (parent, name, attrs, kind)
2572 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2574 protected override TypeAttributes TypeAttr {
2576 TypeAttributes ta = base.TypeAttr;
2577 if (!has_static_constructor)
2578 ta |= TypeAttributes.BeforeFieldInit;
2580 if (Kind == MemberKind.Class) {
2581 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2583 ta |= StaticClassAttribute;
2585 ta |= TypeAttributes.SequentialLayout;
2592 public override void AddNameToContainer (MemberCore symbol, string name)
2594 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2595 if (symbol is TypeParameter) {
2596 Report.Error (694, symbol.Location,
2597 "Type parameter `{0}' has same name as containing type, or method",
2598 symbol.GetSignatureForError ());
2602 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2603 if (imb == null || !imb.IsExplicitImpl) {
2604 Report.SymbolRelatedToPreviousError (this);
2605 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2606 symbol.GetSignatureForError ());
2611 base.AddNameToContainer (symbol, name);
2614 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2616 if (a.IsValidSecurityAttribute ()) {
2617 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2621 if (a.Type == pa.StructLayout) {
2622 PartialContainer.HasStructLayout = true;
2623 if (a.IsExplicitLayoutKind ())
2624 PartialContainer.HasExplicitLayout = true;
2627 if (a.Type == pa.Dynamic) {
2628 a.Error_MisusedDynamicAttribute ();
2632 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2636 /// Defines the default constructors
2638 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2640 // The default instance constructor is public
2641 // If the class is abstract, the default constructor is protected
2642 // The default static constructor is private
2645 ParametersCompiled parameters = null;
2647 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2648 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2650 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2651 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2654 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2655 if (Kind == MemberKind.Class)
2656 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2658 if (PrimaryConstructorParameters != null && !is_static) {
2659 c.IsPrimaryConstructor = true;
2660 c.caching_flags |= Flags.MethodOverloadsExist;
2663 AddConstructor (c, true);
2664 if (PrimaryConstructorBlock == null) {
2665 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2666 IsCompilerGenerated = true
2669 c.Block = PrimaryConstructorBlock;
2675 protected override bool DoDefineMembers ()
2677 CheckProtectedModifier ();
2679 if (PrimaryConstructorParameters != null) {
2681 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2682 if (p.Name == MemberName.Name) {
2683 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2684 GetSignatureForError ());
2687 if (CurrentTypeParameters != null) {
2688 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2689 var tp = CurrentTypeParameters [i];
2690 if (p.Name == tp.Name) {
2691 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2692 GetSignatureForError (), p.GetSignatureForError ());
2699 base.DoDefineMembers ();
2704 public override void PrepareEmit ()
2706 var s = this as Struct;
2707 if (s == null || !s.HasUnmanagedCheckDone) {
2708 for (int i = 0; i < Members.Count; ++i) {
2709 var f = Members [i] as Field;
2710 if (f == null || f.MemberType == null || !f.MemberType.IsPointer)
2713 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2717 base.PrepareEmit ();
2720 public override void Emit ()
2722 if (!has_static_constructor && HasStaticFieldInitializer) {
2723 var c = DefineDefaultConstructor (true);
2729 if (declarative_security != null) {
2730 foreach (var de in declarative_security) {
2732 TypeBuilder.__AddDeclarativeSecurity (de);
2734 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2742 public sealed class Class : ClassOrStruct
2744 const Modifiers AllowedModifiers =
2747 Modifiers.PROTECTED |
2748 Modifiers.INTERNAL |
2750 Modifiers.ABSTRACT |
2755 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2756 : base (parent, name, attrs, MemberKind.Class)
2758 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2759 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2760 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2763 public override void Accept (StructuralVisitor visitor)
2765 visitor.Visit (this);
2768 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2770 var pmn = MemberName;
2771 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2772 Report.Error (537, Location,
2773 "The class System.Object cannot have a base class or implement an interface.");
2775 base.SetBaseTypes (baseTypes);
2778 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2780 if (a.Type == pa.AttributeUsage) {
2781 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2782 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2786 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2787 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2791 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2792 a.Error_MissingGuidAttribute ();
2796 if (a.Type == pa.Extension) {
2797 a.Error_MisusedExtensionAttribute ();
2801 if (a.Type.IsConditionallyExcluded (this))
2804 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2807 public override AttributeTargets AttributeTargets {
2809 return AttributeTargets.Class;
2813 protected override bool DoDefineMembers ()
2815 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2816 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2819 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2820 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2824 if (PrimaryConstructorParameters != null) {
2825 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2826 PrimaryConstructorParameters = null;
2829 foreach (var m in Members) {
2830 if (m is Operator) {
2831 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2835 if (m is Destructor) {
2836 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2841 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2845 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2848 if (m is Constructor) {
2849 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2853 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2856 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2857 generated_primary_constructor = DefineDefaultConstructor (false);
2860 return base.DoDefineMembers ();
2863 public override void Emit ()
2867 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2868 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2870 if (base_type != null && base_type.HasDynamicElement) {
2871 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2875 public override void GetCompletionStartingWith (string prefix, List<string> results)
2877 base.GetCompletionStartingWith (prefix, results);
2880 while (bt != null) {
2881 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2886 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2888 var ifaces = base.ResolveBaseTypes (out base_class);
2890 if (base_class == null) {
2891 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2892 base_type = Compiler.BuiltinTypes.Object;
2894 if (base_type.IsGenericParameter){
2895 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2896 GetSignatureForError (), base_type.GetSignatureForError ());
2897 } else if (base_type.IsStatic) {
2898 Report.SymbolRelatedToPreviousError (base_type);
2899 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2900 GetSignatureForError (), base_type.GetSignatureForError ());
2901 } else if (base_type.IsSealed) {
2902 Report.SymbolRelatedToPreviousError (base_type);
2903 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2904 GetSignatureForError (), base_type.GetSignatureForError ());
2905 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2906 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2907 GetSignatureForError (), base_type.GetSignatureForError ());
2910 switch (base_type.BuiltinType) {
2911 case BuiltinTypeSpec.Type.Enum:
2912 case BuiltinTypeSpec.Type.ValueType:
2913 case BuiltinTypeSpec.Type.MulticastDelegate:
2914 case BuiltinTypeSpec.Type.Delegate:
2915 case BuiltinTypeSpec.Type.Array:
2916 if (!(spec is BuiltinTypeSpec)) {
2917 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2918 GetSignatureForError (), base_type.GetSignatureForError ());
2920 base_type = Compiler.BuiltinTypes.Object;
2925 if (!IsAccessibleAs (base_type)) {
2926 Report.SymbolRelatedToPreviousError (base_type);
2927 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2928 base_type.GetSignatureForError (), GetSignatureForError ());
2932 if (PartialContainer.IsStatic && ifaces != null) {
2933 foreach (var t in ifaces)
2934 Report.SymbolRelatedToPreviousError (t);
2935 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2941 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2942 /// Valid only for attribute classes.
2943 public override string[] ConditionalConditions ()
2945 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2948 caching_flags &= ~Flags.Excluded_Undetected;
2950 if (OptAttributes == null)
2953 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2957 string[] conditions = new string[attrs.Length];
2958 for (int i = 0; i < conditions.Length; ++i)
2959 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2961 caching_flags |= Flags.Excluded;
2966 public sealed class Struct : ClassOrStruct
2968 bool is_unmanaged, has_unmanaged_check_done, requires_delayed_unmanagedtype_check;
2972 // Modifiers allowed in a struct declaration
2974 const Modifiers AllowedModifiers =
2977 Modifiers.PROTECTED |
2978 Modifiers.INTERNAL |
2982 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2983 : base (parent, name, attrs, MemberKind.Struct)
2985 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2986 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2987 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2990 public override AttributeTargets AttributeTargets {
2992 return AttributeTargets.Struct;
2996 public override void Accept (StructuralVisitor visitor)
2998 visitor.Visit (this);
3001 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3003 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3006 // When struct constains fixed fixed and struct layout has explicitly
3007 // set CharSet, its value has to be propagated to compiler generated
3010 if (a.Type == pa.StructLayout) {
3011 var value = a.GetNamedValue ("CharSet");
3015 for (int i = 0; i < Members.Count; ++i) {
3016 FixedField ff = Members [i] as FixedField;
3020 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3025 bool CheckStructCycles ()
3031 foreach (var member in Members) {
3032 var field = member as Field;
3036 TypeSpec ftype = field.Spec.MemberType;
3037 if (!ftype.IsStruct)
3040 if (ftype is BuiltinTypeSpec)
3043 foreach (var targ in ftype.TypeArguments) {
3044 if (!CheckFieldTypeCycle (targ)) {
3045 Report.Error (523, field.Location,
3046 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3047 field.GetSignatureForError (), ftype.GetSignatureForError ());
3053 // Static fields of exactly same type are allowed
3055 if (field.IsStatic && ftype == CurrentType)
3058 if (!CheckFieldTypeCycle (ftype)) {
3059 Report.Error (523, field.Location,
3060 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3061 field.GetSignatureForError (), ftype.GetSignatureForError ());
3070 static bool CheckFieldTypeCycle (TypeSpec ts)
3072 var fts = ts.MemberDefinition as Struct;
3076 return fts.CheckStructCycles ();
3079 protected override bool DoDefineMembers ()
3081 var res = base.DoDefineMembers ();
3083 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3084 generated_primary_constructor = DefineDefaultConstructor (false);
3085 generated_primary_constructor.Define ();
3091 public override void Emit ()
3093 CheckStructCycles ();
3098 public bool HasUnmanagedCheckDone {
3100 return has_unmanaged_check_done;
3104 bool HasUserDefaultConstructor ()
3106 foreach (var m in PartialContainer.Members) {
3107 var c = m as Constructor;
3111 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3118 public override bool IsUnmanagedType ()
3120 if (has_unmanaged_check_done)
3121 return is_unmanaged;
3123 if (requires_delayed_unmanagedtype_check)
3126 var parent_def = Parent.PartialContainer;
3127 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3128 has_unmanaged_check_done = true;
3132 if (first_nonstatic_field != null) {
3133 requires_delayed_unmanagedtype_check = true;
3135 foreach (var member in Members) {
3136 var f = member as Field;
3143 // It can happen when recursive unmanaged types are defined
3144 // struct S { S* s; }
3145 TypeSpec mt = f.MemberType;
3153 has_unmanaged_check_done = true;
3157 has_unmanaged_check_done = true;
3160 is_unmanaged = true;
3164 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3166 var ifaces = base.ResolveBaseTypes (out base_class);
3167 base_type = Compiler.BuiltinTypes.ValueType;
3175 public sealed class Interface : TypeDefinition {
3178 /// Modifiers allowed in a class declaration
3180 const Modifiers AllowedModifiers =
3183 Modifiers.PROTECTED |
3184 Modifiers.INTERNAL |
3188 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3189 : base (parent, name, attrs, MemberKind.Interface)
3191 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3193 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3194 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3199 public override AttributeTargets AttributeTargets {
3201 return AttributeTargets.Interface;
3205 protected override TypeAttributes TypeAttr {
3207 const TypeAttributes DefaultTypeAttributes =
3208 TypeAttributes.AutoLayout |
3209 TypeAttributes.Abstract |
3210 TypeAttributes.Interface;
3212 return base.TypeAttr | DefaultTypeAttributes;
3218 public override void Accept (StructuralVisitor visitor)
3220 visitor.Visit (this);
3223 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3225 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3226 a.Error_MissingGuidAttribute ();
3230 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3233 protected override bool VerifyClsCompliance ()
3235 if (!base.VerifyClsCompliance ())
3238 if (iface_exprs != null) {
3239 foreach (var iface in iface_exprs) {
3240 if (iface.IsCLSCompliant ())
3243 Report.SymbolRelatedToPreviousError (iface);
3244 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3245 GetSignatureForError (), iface.GetSignatureForError ());
3253 public abstract class InterfaceMemberBase : MemberBase
3256 // Common modifiers allowed in a class declaration
3258 protected const Modifiers AllowedModifiersClass =
3261 Modifiers.PROTECTED |
3262 Modifiers.INTERNAL |
3267 Modifiers.OVERRIDE |
3268 Modifiers.ABSTRACT |
3273 // Common modifiers allowed in a struct declaration
3275 protected const Modifiers AllowedModifiersStruct =
3278 Modifiers.PROTECTED |
3279 Modifiers.INTERNAL |
3282 Modifiers.OVERRIDE |
3287 // Common modifiers allowed in a interface declaration
3289 protected const Modifiers AllowedModifiersInterface =
3294 // Whether this is an interface member.
3296 public bool IsInterface;
3299 // If true, this is an explicit interface implementation
3301 public readonly bool IsExplicitImpl;
3303 protected bool is_external_implementation;
3306 // The interface type we are explicitly implementing
3308 public TypeSpec InterfaceType;
3311 // The method we're overriding if this is an override method.
3313 protected MethodSpec base_method;
3315 readonly Modifiers explicit_mod_flags;
3316 public MethodAttributes flags;
3318 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3319 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3321 IsInterface = parent.Kind == MemberKind.Interface;
3322 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3323 explicit_mod_flags = mod;
3326 public abstract Variance ExpectedMemberTypeVariance { get; }
3328 protected override bool CheckBase ()
3330 if (!base.CheckBase ())
3333 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3334 CheckForDuplications ();
3339 // For System.Object only
3340 if (Parent.BaseType == null)
3343 MemberSpec candidate;
3344 bool overrides = false;
3345 var base_member = FindBaseMember (out candidate, ref overrides);
3347 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3348 if (base_member == null) {
3349 if (candidate == null) {
3350 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3351 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3352 "object.Finalize()");
3354 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3355 GetSignatureForError (), SimpleName.GetMemberType (this));
3358 Report.SymbolRelatedToPreviousError (candidate);
3360 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3361 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3362 else if (this is PropertyBase)
3363 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3364 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3366 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3367 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3374 // Handles ambiguous overrides
3376 if (candidate != null) {
3377 Report.SymbolRelatedToPreviousError (candidate);
3378 Report.SymbolRelatedToPreviousError (base_member);
3380 // Get member definition for error reporting
3381 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3382 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3384 Report.Error (462, Location,
3385 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3386 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3389 if (!CheckOverrideAgainstBase (base_member))
3392 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3394 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3395 Report.SymbolRelatedToPreviousError (base_member);
3396 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3397 GetSignatureForError (), base_member.GetSignatureForError ());
3400 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3401 Report.SymbolRelatedToPreviousError (base_member);
3402 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3403 GetSignatureForError (), base_member.GetSignatureForError ());
3407 base_method = base_member as MethodSpec;
3411 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3412 base_member = candidate;
3414 if (base_member == null) {
3415 if ((ModFlags & Modifiers.NEW) != 0) {
3416 if (base_member == null) {
3417 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3418 GetSignatureForError ());
3422 if ((ModFlags & Modifiers.NEW) == 0) {
3423 ModFlags |= Modifiers.NEW;
3424 if (!IsCompilerGenerated) {
3425 Report.SymbolRelatedToPreviousError (base_member);
3426 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3427 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",
3428 GetSignatureForError (), base_member.GetSignatureForError ());
3430 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3431 GetSignatureForError (), base_member.GetSignatureForError ());
3436 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3437 switch (base_member.Kind) {
3438 case MemberKind.Event:
3439 case MemberKind.Indexer:
3440 case MemberKind.Method:
3441 case MemberKind.Property:
3442 Report.SymbolRelatedToPreviousError (base_member);
3443 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3444 GetSignatureForError (), base_member.GetSignatureForError ());
3453 protected virtual bool CheckForDuplications ()
3455 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3459 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3460 // that have been defined.
3462 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3466 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3467 Report.SymbolRelatedToPreviousError (base_member);
3468 Report.Error (506, Location,
3469 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3470 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3474 // Now we check that the overriden method is not final
3475 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3476 Report.SymbolRelatedToPreviousError (base_member);
3477 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3478 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3482 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3483 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3484 Report.SymbolRelatedToPreviousError (base_member);
3485 if (this is PropertyBasedMember) {
3486 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3487 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3489 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3490 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3498 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3500 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3501 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3503 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3505 // It must be at least "protected"
3507 if ((thisp & Modifiers.PROTECTED) == 0) {
3512 // when overriding protected internal, the method can be declared
3513 // protected internal only within the same assembly or assembly
3514 // which has InternalsVisibleTo
3516 if ((thisp & Modifiers.INTERNAL) != 0) {
3517 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3521 // protected overriding protected internal inside same assembly
3522 // requires internal modifier as well
3524 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3531 return thisp == base_classp;
3534 public override bool Define ()
3537 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3538 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3540 flags = MethodAttributes.Public |
3541 MethodAttributes.Abstract |
3542 MethodAttributes.HideBySig |
3543 MethodAttributes.NewSlot |
3544 MethodAttributes.Virtual;
3546 Parent.PartialContainer.MethodModifiersValid (this);
3548 flags = ModifiersExtensions.MethodAttr (ModFlags);
3551 if (IsExplicitImpl) {
3552 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3553 if (InterfaceType == null)
3556 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3557 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3558 GetSignatureForError ());
3561 if (!InterfaceType.IsInterface) {
3562 Report.SymbolRelatedToPreviousError (InterfaceType);
3563 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3564 InterfaceType.GetSignatureForError ());
3566 Parent.PartialContainer.VerifyImplements (this);
3569 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3571 allowed_explicit |= Modifiers.ASYNC;
3573 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3576 return base.Define ();
3579 protected bool DefineParameters (ParametersCompiled parameters)
3581 if (!parameters.Resolve (this))
3585 for (int i = 0; i < parameters.Count; ++i) {
3586 Parameter p = parameters [i];
3588 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3589 p.Warning_UselessOptionalParameter (Report);
3591 if (p.CheckAccessibility (this))
3594 TypeSpec t = parameters.Types [i];
3595 Report.SymbolRelatedToPreviousError (t);
3596 if (this is Indexer)
3597 Report.Error (55, Location,
3598 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3599 t.GetSignatureForError (), GetSignatureForError ());
3600 else if (this is Operator)
3601 Report.Error (57, Location,
3602 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3603 t.GetSignatureForError (), GetSignatureForError ());
3605 Report.Error (51, Location,
3606 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3607 t.GetSignatureForError (), GetSignatureForError ());
3613 protected override void DoMemberTypeDependentChecks ()
3615 base.DoMemberTypeDependentChecks ();
3617 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3620 public override void Emit()
3622 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3623 // We are more strict than csc and report this as an error because SRE does not allow emit that
3624 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3625 if (this is Constructor) {
3626 Report.Warning (824, 1, Location,
3627 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3629 Report.Warning (626, 1, Location,
3630 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3631 GetSignatureForError ());
3638 public override bool EnableOverloadChecks (MemberCore overload)
3641 // Two members can differ in their explicit interface
3642 // type parameter only
3644 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3645 if (imb != null && imb.IsExplicitImpl) {
3646 if (IsExplicitImpl) {
3647 caching_flags |= Flags.MethodOverloadsExist;
3652 return IsExplicitImpl;
3655 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3657 var base_modifiers = base_member.Modifiers;
3659 // Remove internal modifier from types which are not internally accessible
3660 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3661 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3662 base_modifiers = Modifiers.PROTECTED;
3664 Report.SymbolRelatedToPreviousError (base_member);
3665 Report.Error (507, member.Location,
3666 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3667 member.GetSignatureForError (),
3668 ModifiersExtensions.AccessibilityName (base_modifiers),
3669 base_member.GetSignatureForError ());
3672 protected void Error_StaticReturnType ()
3674 Report.Error (722, Location,
3675 "`{0}': static types cannot be used as return types",
3676 MemberType.GetSignatureForError ());
3680 /// Gets base method and its return type
3682 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3684 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3688 // The "short" name of this property / indexer / event. This is the
3689 // name without the explicit interface.
3691 public string ShortName {
3692 get { return MemberName.Name; }
3696 // Returns full metadata method name
3698 public string GetFullName (MemberName name)
3700 return GetFullName (name.Name);
3703 public string GetFullName (string name)
3705 if (!IsExplicitImpl)
3709 // When dealing with explicit members a full interface type
3710 // name is added to member name to avoid possible name conflicts
3712 // We use CSharpName which gets us full name with benefit of
3713 // replacing predefined names which saves some space and name
3716 return InterfaceType.GetSignatureForError () + "." + name;
3719 public override string GetSignatureForDocumentation ()
3722 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3724 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3727 public override bool IsUsed
3729 get { return IsExplicitImpl || base.IsUsed; }
3732 public override void SetConstraints (List<Constraints> constraints_list)
3734 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3735 Report.Error (460, Location,
3736 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3737 GetSignatureForError ());
3740 base.SetConstraints (constraints_list);
3744 public abstract class MemberBase : MemberCore
3746 protected FullNamedExpression type_expr;
3747 protected TypeSpec member_type;
3748 public new TypeDefinition Parent;
3750 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3751 : base (parent, name, attrs)
3753 this.Parent = parent;
3754 this.type_expr = type;
3756 if (name != MemberName.Null)
3757 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3762 public TypeSpec MemberType {
3768 public FullNamedExpression TypeExpression {
3780 // Main member define entry
3782 public override bool Define ()
3784 DoMemberTypeIndependentChecks ();
3787 // Returns false only when type resolution failed
3789 if (!ResolveMemberType ())
3792 DoMemberTypeDependentChecks ();
3797 // Any type_name independent checks
3799 protected virtual void DoMemberTypeIndependentChecks ()
3801 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3802 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3803 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3804 GetSignatureForError (), Parent.GetSignatureForError ());
3809 // Any type_name dependent checks
3811 protected virtual void DoMemberTypeDependentChecks ()
3813 // verify accessibility
3814 if (!IsAccessibleAs (MemberType)) {
3815 Report.SymbolRelatedToPreviousError (MemberType);
3816 if (this is Property)
3817 Report.Error (53, Location,
3818 "Inconsistent accessibility: property type `" +
3819 MemberType.GetSignatureForError () + "' is less " +
3820 "accessible than property `" + GetSignatureForError () + "'");
3821 else if (this is Indexer)
3822 Report.Error (54, Location,
3823 "Inconsistent accessibility: indexer return type `" +
3824 MemberType.GetSignatureForError () + "' is less " +
3825 "accessible than indexer `" + GetSignatureForError () + "'");
3826 else if (this is MethodCore) {
3827 if (this is Operator)
3828 Report.Error (56, Location,
3829 "Inconsistent accessibility: return type `" +
3830 MemberType.GetSignatureForError () + "' is less " +
3831 "accessible than operator `" + GetSignatureForError () + "'");
3833 Report.Error (50, Location,
3834 "Inconsistent accessibility: return type `" +
3835 MemberType.GetSignatureForError () + "' is less " +
3836 "accessible than method `" + GetSignatureForError () + "'");
3837 } else if (this is Event) {
3838 Report.Error (7025, Location,
3839 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3840 MemberType.GetSignatureForError (), GetSignatureForError ());
3842 Report.Error (52, Location,
3843 "Inconsistent accessibility: field type `" +
3844 MemberType.GetSignatureForError () + "' is less " +
3845 "accessible than field `" + GetSignatureForError () + "'");
3850 protected void IsTypePermitted ()
3852 if (MemberType.IsSpecialRuntimeType) {
3853 if (Parent is StateMachine) {
3854 Report.Error (4012, Location,
3855 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3856 MemberType.GetSignatureForError ());
3857 } else if (Parent is HoistedStoreyClass) {
3858 Report.Error (4013, Location,
3859 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3860 MemberType.GetSignatureForError ());
3862 Report.Error (610, Location,
3863 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3868 protected virtual bool CheckBase ()
3870 CheckProtectedModifier ();
3875 public override string GetSignatureForDocumentation ()
3877 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3880 public virtual void PrepareEmit ()
3882 if (member_type != null && type_expr != null)
3883 member_type.CheckObsoleteness (this, type_expr.Location);
3886 protected virtual bool ResolveMemberType ()
3888 if (member_type != null)
3889 throw new InternalErrorException ("Multi-resolve");
3891 member_type = type_expr.ResolveAsType (this);
3892 return member_type != null;