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. User
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 string GetSignatureForMetadata ()
364 if (Parent is TypeDefinition) {
365 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
368 var sb = new StringBuilder ();
369 CreateMetadataName (sb);
370 return sb.ToString ();
373 public virtual void RemoveContainer (TypeContainer cont)
375 if (containers != null)
376 containers.Remove (cont);
378 var tc = Parent == Module ? Module : this;
379 tc.defined_names.Remove (cont.MemberName.Basename);
382 public virtual void VerifyMembers ()
384 if (containers != null) {
385 foreach (TypeContainer tc in containers)
390 public override void WriteDebugSymbol (MonoSymbolFile file)
392 if (containers != null) {
393 foreach (TypeContainer tc in containers) {
394 tc.WriteDebugSymbol (file);
400 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
403 // Different context is needed when resolving type container base
404 // types. Type names come from the parent scope but type parameter
405 // names from the container scope.
407 public struct BaseContext : IMemberContext
411 public BaseContext (TypeContainer tc)
416 #region IMemberContext Members
418 public CompilerContext Compiler {
419 get { return tc.Compiler; }
422 public TypeSpec CurrentType {
423 get { return tc.PartialContainer.CurrentType; }
426 public TypeParameters CurrentTypeParameters {
427 get { return tc.PartialContainer.CurrentTypeParameters; }
430 public MemberCore CurrentMemberDefinition {
434 public bool IsObsolete {
435 get { return tc.IsObsolete; }
438 public bool IsUnsafe {
439 get { return tc.IsUnsafe; }
442 public bool IsStatic {
443 get { return tc.IsStatic; }
446 public ModuleContainer Module {
447 get { return tc.Module; }
450 public string GetSignatureForError ()
452 return tc.GetSignatureForError ();
455 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
460 public FullNamedExpression LookupNamespaceAlias (string name)
462 return tc.Parent.LookupNamespaceAlias (name);
465 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
468 var tp = CurrentTypeParameters;
470 TypeParameter t = tp.Find (name);
472 return new TypeParameterExpr (t, loc);
476 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
486 GetHashCode = 1 << 1,
487 HasStaticFieldInitializer = 1 << 2
490 readonly List<MemberCore> members;
492 // Holds a list of fields that have initializers
493 protected List<FieldInitializer> initialized_fields;
495 // Holds a list of static fields that have initializers
496 protected List<FieldInitializer> initialized_static_fields;
498 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
500 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
503 // Points to the first non-static field added to the container.
505 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
506 // and the first one's as good as any.
508 protected FieldBase first_nonstatic_field;
511 // This one is computed after we can distinguish interfaces
512 // from classes from the arraylist `type_bases'
514 protected TypeSpec base_type;
515 FullNamedExpression base_type_expr; // TODO: It's temporary variable
516 protected TypeSpec[] iface_exprs;
518 protected List<FullNamedExpression> type_bases;
520 // Partial parts for classes only
521 List<TypeDefinition> class_partial_parts;
523 TypeDefinition InTransit;
525 public TypeBuilder TypeBuilder;
526 GenericTypeParameterBuilder[] all_tp_builders;
528 // All recursive type parameters put together sharing same
529 // TypeParameter instances
531 TypeParameters all_type_parameters;
533 public const string DefaultIndexerName = "Item";
535 bool has_normal_indexers;
537 protected bool requires_delayed_unmanagedtype_check;
539 bool members_defined;
540 bool members_defined_ok;
541 protected bool has_static_constructor;
543 private CachedMethods cached_method;
545 protected TypeSpec spec;
546 TypeSpec current_type;
548 public int DynamicSitesCounter;
549 public int AnonymousMethodsCounter;
550 public int MethodGroupsCounter;
552 static readonly string[] attribute_targets = new [] { "type" };
553 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
556 /// The pending methods that need to be implemented
557 // (interfaces or abstract methods)
559 PendingImplementation pending;
561 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
562 : base (parent, name, attrs, kind)
564 PartialContainer = this;
565 members = new List<MemberCore> ();
570 public List<FullNamedExpression> BaseTypeExpressions {
576 public override TypeSpec CurrentType {
578 if (current_type == null) {
579 if (IsGenericOrParentIsGeneric) {
581 // Switch to inflated version as it's used by all expressions
583 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
584 current_type = spec.MakeGenericType (this, targs);
594 public override TypeParameters CurrentTypeParameters {
596 return PartialContainer.MemberName.TypeParameters;
600 int CurrentTypeParametersStartIndex {
602 int total = all_tp_builders.Length;
603 if (CurrentTypeParameters != null) {
604 return total - CurrentTypeParameters.Count;
610 public virtual AssemblyDefinition DeclaringAssembly {
612 return Module.DeclaringAssembly;
616 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
618 return Module.DeclaringAssembly;
622 public TypeSpec Definition {
628 public bool HasMembersDefined {
630 return members_defined;
634 public bool HasInstanceConstructor {
636 return (caching_flags & Flags.HasInstanceConstructor) != 0;
639 caching_flags |= Flags.HasInstanceConstructor;
643 // Indicated whether container has StructLayout attribute set Explicit
644 public bool HasExplicitLayout {
645 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
646 set { caching_flags |= Flags.HasExplicitLayout; }
649 public bool HasOperators {
651 return (caching_flags & Flags.HasUserOperators) != 0;
654 caching_flags |= Flags.HasUserOperators;
658 public bool HasStructLayout {
659 get { return (caching_flags & Flags.HasStructLayout) != 0; }
660 set { caching_flags |= Flags.HasStructLayout; }
663 public TypeSpec[] Interfaces {
669 public bool IsGenericOrParentIsGeneric {
671 return all_type_parameters != null;
675 public bool IsTopLevel {
677 return !(Parent is TypeDefinition);
681 public bool IsPartial {
683 return (ModFlags & Modifiers.PARTIAL) != 0;
687 bool ITypeDefinition.IsTypeForwarder {
693 bool ITypeDefinition.IsCyclicTypeForwarder {
700 // Returns true for secondary partial containers
704 return PartialContainer != this;
708 public MemberCache MemberCache {
710 return spec.MemberCache;
714 public List<MemberCore> Members {
720 string ITypeDefinition.Namespace {
723 while (p.Kind != MemberKind.Namespace)
726 return p.MemberName == null ? null : p.GetSignatureForError ();
730 public ParametersCompiled PrimaryConstructorParameters { get; set; }
732 public Arguments PrimaryConstructorBaseArguments { get; set; }
734 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
736 public TypeParameters TypeParametersAll {
738 return all_type_parameters;
742 public override string[] ValidAttributeTargets {
744 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
750 public override void Accept (StructuralVisitor visitor)
752 visitor.Visit (this);
755 public void AddMember (MemberCore symbol)
757 if (symbol.MemberName.ExplicitInterface != null) {
758 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
759 Report.Error (541, symbol.Location,
760 "`{0}': explicit interface declaration can only be declared in a class or struct",
761 symbol.GetSignatureForError ());
765 AddNameToContainer (symbol, symbol.MemberName.Name);
766 members.Add (symbol);
769 public override void AddTypeContainer (TypeContainer tc)
771 AddNameToContainer (tc, tc.MemberName.Basename);
773 base.AddTypeContainer (tc);
776 protected override void AddTypeContainerMember (TypeContainer tc)
780 if (containers == null)
781 containers = new List<TypeContainer> ();
783 base.AddTypeContainerMember (tc);
787 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
789 public virtual void AddNameToContainer (MemberCore symbol, string name)
791 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
795 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
796 PartialContainer.defined_names.Add (name, symbol);
800 if (symbol.EnableOverloadChecks (mc))
803 InterfaceMemberBase im = mc as InterfaceMemberBase;
804 if (im != null && im.IsExplicitImpl)
807 Report.SymbolRelatedToPreviousError (mc);
808 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
809 Error_MissingPartialModifier (symbol);
813 if (symbol is TypeParameter) {
814 Report.Error (692, symbol.Location,
815 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
817 Report.Error (102, symbol.Location,
818 "The type `{0}' already contains a definition for `{1}'",
819 GetSignatureForError (), name);
825 public void AddConstructor (Constructor c)
827 AddConstructor (c, false);
830 public void AddConstructor (Constructor c, bool isDefault)
832 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
834 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
836 if (is_static && c.ParameterInfo.IsEmpty) {
837 PartialContainer.has_static_constructor = true;
839 PartialContainer.HasInstanceConstructor = true;
845 public bool AddField (FieldBase field)
849 if ((field.ModFlags & Modifiers.STATIC) != 0)
852 var first_field = PartialContainer.first_nonstatic_field;
853 if (first_field == null) {
854 PartialContainer.first_nonstatic_field = field;
858 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
859 Report.SymbolRelatedToPreviousError (first_field.Parent);
860 Report.Warning (282, 3, field.Location,
861 "struct instance field `{0}' found in different declaration from instance field `{1}'",
862 field.GetSignatureForError (), first_field.GetSignatureForError ());
868 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
870 public void AddIndexer (Indexer i)
875 public void AddOperator (Operator op)
877 PartialContainer.HasOperators = true;
881 public void AddPartialPart (TypeDefinition part)
883 if (Kind != MemberKind.Class)
886 if (class_partial_parts == null)
887 class_partial_parts = new List<TypeDefinition> ();
889 class_partial_parts.Add (part);
892 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
894 if (a.Target == AttributeTargets.Method) {
895 foreach (var m in members) {
896 var c = m as Constructor;
900 if (c.IsPrimaryConstructor) {
901 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
906 throw new InternalErrorException ();
909 if (has_normal_indexers && a.Type == pa.DefaultMember) {
910 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
914 if (a.Type == pa.Required) {
915 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
919 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
922 public override AttributeTargets AttributeTargets {
924 throw new NotSupportedException ();
928 public TypeSpec BaseType {
930 return spec.BaseType;
934 protected virtual TypeAttributes TypeAttr {
936 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
940 public int TypeParametersCount {
942 return MemberName.Arity;
946 TypeParameterSpec[] ITypeDefinition.TypeParameters {
948 return PartialContainer.CurrentTypeParameters.Types;
952 public string GetAttributeDefaultMember ()
954 return indexer_name ?? DefaultIndexerName;
957 public bool IsComImport {
959 if (OptAttributes == null)
962 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
966 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
969 PartialContainer.RegisterFieldForInitialization (field, expression);
971 if ((field.ModFlags & Modifiers.STATIC) != 0){
972 if (initialized_static_fields == null) {
973 HasStaticFieldInitializer = true;
974 initialized_static_fields = new List<FieldInitializer> (4);
977 initialized_static_fields.Add (expression);
979 if (Kind == MemberKind.Struct) {
980 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
981 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
982 GetSignatureForError ());
986 if (initialized_fields == null)
987 initialized_fields = new List<FieldInitializer> (4);
989 initialized_fields.Add (expression);
993 public void ResolveFieldInitializers (BlockContext ec)
995 Debug.Assert (!IsPartialPart);
998 if (initialized_static_fields == null)
1001 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
1003 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1004 for (i = 0; i < initialized_static_fields.Count; ++i) {
1005 FieldInitializer fi = initialized_static_fields [i];
1006 ExpressionStatement s = fi.ResolveStatement (ec);
1008 s = EmptyExpressionStatement.Instance;
1009 } else if (!fi.IsSideEffectFree) {
1010 has_complex_initializer = true;
1016 for (i = 0; i < initialized_static_fields.Count; ++i) {
1017 FieldInitializer fi = initialized_static_fields [i];
1019 // Need special check to not optimize code like this
1020 // static int a = b = 5;
1021 // static int b = 0;
1023 if (!has_complex_initializer && fi.IsDefaultInitializer)
1026 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1027 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1033 if (initialized_fields == null)
1036 for (int i = 0; i < initialized_fields.Count; ++i) {
1037 FieldInitializer fi = initialized_fields [i];
1040 // Clone before resolving otherwise when field initializer is needed
1041 // in more than 1 constructor any resolve after the initial one would
1042 // only took the resolved expression which is problem for expressions
1043 // that generate extra expressions or code during Resolve phase
1045 var cloned = fi.Clone (new CloneContext ());
1047 ExpressionStatement s = fi.ResolveStatement (ec);
1049 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1054 // Field is re-initialized to its default value => removed
1056 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1059 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1060 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1061 initialized_fields [i] = (FieldInitializer) cloned;
1065 public override string DocComment {
1077 public PendingImplementation PendingImplementations {
1078 get { return pending; }
1081 internal override void GenerateDocComment (DocumentationBuilder builder)
1086 base.GenerateDocComment (builder);
1088 foreach (var member in members)
1089 member.GenerateDocComment (builder);
1092 public TypeSpec GetAttributeCoClass ()
1094 if (OptAttributes == null)
1097 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1101 return a.GetCoClassAttributeValue ();
1104 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1107 if (OptAttributes != null) {
1108 a = OptAttributes.Search (pa);
1114 return a.GetAttributeUsageAttribute ();
1117 public virtual CompilationSourceFile GetCompilationSourceFile ()
1119 TypeContainer ns = Parent;
1121 var sf = ns as CompilationSourceFile;
1129 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1131 type_bases = baseTypes;
1135 /// This function computes the Base class and also the
1136 /// list of interfaces that the class or struct @c implements.
1138 /// The return value is an array (might be null) of
1139 /// interfaces implemented (as Types).
1141 /// The @base_class argument is set to the base object or null
1142 /// if this is `System.Object'.
1144 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1147 if (type_bases == null)
1150 int count = type_bases.Count;
1151 TypeSpec[] ifaces = null;
1152 var base_context = new BaseContext (this);
1153 for (int i = 0, j = 0; i < count; i++){
1154 FullNamedExpression fne = type_bases [i];
1156 var fne_resolved = fne.ResolveAsType (base_context);
1157 if (fne_resolved == null)
1160 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1161 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1162 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1163 GetSignatureForError ());
1168 base_type = fne_resolved;
1174 ifaces = new TypeSpec [count - i];
1176 if (fne_resolved.IsInterface) {
1177 for (int ii = 0; ii < j; ++ii) {
1178 if (fne_resolved == ifaces [ii]) {
1179 Report.Error (528, Location, "`{0}' is already listed in interface list",
1180 fne_resolved.GetSignatureForError ());
1185 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1186 Report.Error (61, fne.Location,
1187 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1188 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1191 Report.SymbolRelatedToPreviousError (fne_resolved);
1192 if (Kind != MemberKind.Class) {
1193 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1194 } else if (base_class != null)
1195 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1196 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1198 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1199 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1203 ifaces [j++] = fne_resolved;
1210 // Checks that some operators come in pairs:
1216 // They are matched based on the return type and the argument types
1218 void CheckPairedOperators ()
1220 bool has_equality_or_inequality = false;
1221 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1223 for (int i = 0; i < members.Count; ++i) {
1224 var o_a = members[i] as Operator;
1228 var o_type = o_a.OperatorType;
1229 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1230 has_equality_or_inequality = true;
1232 if (found_matched.Contains (o_type))
1235 var matching_type = o_a.GetMatchingOperator ();
1236 if (matching_type == Operator.OpType.TOP) {
1240 bool pair_found = false;
1241 for (int ii = 0; ii < members.Count; ++ii) {
1242 var o_b = members[ii] as Operator;
1243 if (o_b == null || o_b.OperatorType != matching_type)
1246 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1249 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1252 found_matched.Add (matching_type);
1258 Report.Error (216, o_a.Location,
1259 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1260 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1264 if (has_equality_or_inequality) {
1266 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1267 GetSignatureForError ());
1269 if (!HasGetHashCode)
1270 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1271 GetSignatureForError ());
1275 public override void CreateMetadataName (StringBuilder sb)
1277 if (Parent.MemberName != null) {
1278 Parent.CreateMetadataName (sb);
1280 if (sb.Length != 0) {
1285 sb.Append (MemberName.Basename);
1288 bool CreateTypeBuilder ()
1291 // Sets .size to 1 for structs with no instance fields
1293 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1295 var parent_def = Parent as TypeDefinition;
1296 if (parent_def == null) {
1297 var sb = new StringBuilder ();
1298 CreateMetadataName (sb);
1299 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1301 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (MemberName.Basename, TypeAttr, null, type_size);
1304 if (DeclaringAssembly.Importer != null)
1305 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1307 spec.SetMetaInfo (TypeBuilder);
1308 spec.MemberCache = new MemberCache (this);
1310 TypeParameters parentAllTypeParameters = null;
1311 if (parent_def != null) {
1312 spec.DeclaringType = Parent.CurrentType;
1313 parent_def.MemberCache.AddMember (spec);
1314 parentAllTypeParameters = parent_def.all_type_parameters;
1317 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1318 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1320 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1322 if (CurrentTypeParameters != null) {
1323 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1324 CurrentTypeParameters.Define (all_tp_builders);
1331 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1334 int parent_offset = 0;
1335 if (parentAllTypeParameters != null) {
1336 if (CurrentTypeParameters == null) {
1337 all_type_parameters = parentAllTypeParameters;
1338 return parentAllTypeParameters.GetAllNames ();
1341 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1342 all_type_parameters = new TypeParameters (names.Length);
1343 all_type_parameters.Add (parentAllTypeParameters);
1345 parent_offset = all_type_parameters.Count;
1346 for (int i = 0; i < parent_offset; ++i)
1347 names[i] = all_type_parameters[i].MemberName.Name;
1350 names = new string[CurrentTypeParameters.Count];
1353 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1354 if (all_type_parameters != null)
1355 all_type_parameters.Add (MemberName.TypeParameters[i]);
1357 var name = CurrentTypeParameters[i].MemberName.Name;
1358 names[parent_offset + i] = name;
1359 for (int ii = 0; ii < parent_offset + i; ++ii) {
1360 if (names[ii] != name)
1363 var tp = CurrentTypeParameters[i];
1364 var conflict = all_type_parameters[ii];
1366 tp.WarningParentNameConflict (conflict);
1370 if (all_type_parameters == null)
1371 all_type_parameters = CurrentTypeParameters;
1377 public SourceMethodBuilder CreateMethodSymbolEntry ()
1379 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1382 var source_file = GetCompilationSourceFile ();
1383 if (source_file == null)
1386 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1390 // Creates a proxy base method call inside this container for hoisted base member calls
1392 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1394 Method proxy_method;
1397 // One proxy per base method is enough
1399 if (hoisted_base_call_proxies == null) {
1400 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1401 proxy_method = null;
1403 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1406 if (proxy_method == null) {
1407 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1409 MemberName member_name;
1410 TypeArguments targs = null;
1411 TypeSpec return_type = method.ReturnType;
1412 var local_param_types = method.Parameters.Types;
1414 if (method.IsGeneric) {
1416 // Copy all base generic method type parameters info
1418 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1419 var tparams = new TypeParameters ();
1421 targs = new TypeArguments ();
1422 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1423 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1424 var tp = hoisted_tparams[i];
1425 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1426 tparams.Add (local_tp);
1428 targs.Add (new SimpleName (tp.Name, Location));
1429 targs.Arguments[i] = local_tp.Type;
1432 member_name = new MemberName (name, tparams, Location);
1435 // Mutate any method type parameters from original
1436 // to newly created hoisted version
1438 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1439 return_type = mutator.Mutate (return_type);
1440 local_param_types = mutator.Mutate (local_param_types);
1442 member_name = new MemberName (name);
1445 var base_parameters = new Parameter[method.Parameters.Count];
1446 for (int i = 0; i < base_parameters.Length; ++i) {
1447 var base_param = method.Parameters.FixedParameters[i];
1448 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1449 base_param.Name, base_param.ModFlags, null, Location);
1450 base_parameters[i].Resolve (this, i);
1453 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1454 if (method.Parameters.HasArglist) {
1455 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1456 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1459 // Compiler generated proxy
1460 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1461 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1462 member_name, cloned_params, null);
1464 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1465 IsCompilerGenerated = true
1468 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1469 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1471 mg.SetTypeArguments (rc, targs);
1473 // Get all the method parameters and pass them as arguments
1474 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1475 Statement statement;
1476 if (method.ReturnType.Kind == MemberKind.Void)
1477 statement = new StatementExpression (real_base_call);
1479 statement = new Return (real_base_call, Location);
1481 block.AddStatement (statement);
1482 proxy_method.Block = block;
1484 members.Add (proxy_method);
1485 proxy_method.Define ();
1486 proxy_method.PrepareEmit ();
1488 hoisted_base_call_proxies.Add (method, proxy_method);
1491 return proxy_method.Spec;
1494 protected bool DefineBaseTypes ()
1496 if (IsPartialPart && Kind == MemberKind.Class)
1499 return DoDefineBaseType ();
1502 bool DoDefineBaseType ()
1504 iface_exprs = ResolveBaseTypes (out base_type_expr);
1507 if (IsPartialPart) {
1508 set_base_type = false;
1510 if (base_type_expr != null) {
1511 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1512 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1513 Report.Error (263, Location,
1514 "Partial declarations of `{0}' must not specify different base classes",
1515 GetSignatureForError ());
1517 PartialContainer.base_type_expr = base_type_expr;
1518 PartialContainer.base_type = base_type;
1519 set_base_type = true;
1523 if (iface_exprs != null) {
1524 if (PartialContainer.iface_exprs == null)
1525 PartialContainer.iface_exprs = iface_exprs;
1527 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1528 foreach (var iface_partial in iface_exprs) {
1529 if (ifaces.Contains (iface_partial))
1532 ifaces.Add (iface_partial);
1535 PartialContainer.iface_exprs = ifaces.ToArray ();
1539 PartialContainer.members.AddRange (members);
1540 if (containers != null) {
1541 if (PartialContainer.containers == null)
1542 PartialContainer.containers = new List<TypeContainer> ();
1544 PartialContainer.containers.AddRange (containers);
1547 if (PrimaryConstructorParameters != null) {
1548 if (PartialContainer.PrimaryConstructorParameters != null) {
1549 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1551 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1555 members_defined = members_defined_ok = true;
1556 caching_flags |= Flags.CloseTypeCreated;
1558 set_base_type = true;
1561 var cycle = CheckRecursiveDefinition (this);
1562 if (cycle != null) {
1563 Report.SymbolRelatedToPreviousError (cycle);
1564 if (this is Interface) {
1565 Report.Error (529, Location,
1566 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1567 GetSignatureForError (), cycle.GetSignatureForError ());
1570 PartialContainer.iface_exprs = null;
1572 Report.Error (146, Location,
1573 "Circular base class dependency involving `{0}' and `{1}'",
1574 GetSignatureForError (), cycle.GetSignatureForError ());
1577 PartialContainer.base_type = null;
1581 if (iface_exprs != null) {
1582 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1583 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1586 foreach (var iface_type in iface_exprs) {
1587 // Prevents a crash, the interface might not have been resolved: 442144
1588 if (iface_type == null)
1591 if (!spec.AddInterfaceDefined (iface_type))
1594 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1598 if (Kind == MemberKind.Interface) {
1599 spec.BaseType = Compiler.BuiltinTypes.Object;
1603 if (set_base_type) {
1608 // Base type of partial container has to be resolved before we
1609 // resolve any nested types of the container. We need to know
1610 // partial parts because the base type can be specified in file
1611 // defined after current container
1613 if (class_partial_parts != null) {
1614 foreach (var pp in class_partial_parts) {
1615 if (pp.PrimaryConstructorBaseArguments != null)
1616 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1618 pp.DoDefineBaseType ();
1628 if (base_type == null) {
1629 TypeBuilder.SetParent (null);
1633 if (spec.BaseType == base_type)
1636 spec.BaseType = base_type;
1639 spec.UpdateInflatedInstancesBaseType ();
1641 // Set base type after type creation
1642 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1645 public override void ExpandBaseInterfaces ()
1648 DoExpandBaseInterfaces ();
1650 base.ExpandBaseInterfaces ();
1653 public void DoExpandBaseInterfaces ()
1655 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1658 caching_flags |= Flags.InterfacesExpanded;
1661 // Expand base interfaces. It cannot be done earlier because all partial
1662 // interface parts need to be defined before the type they are used from
1664 if (iface_exprs != null) {
1665 foreach (var iface in iface_exprs) {
1669 var td = iface.MemberDefinition as TypeDefinition;
1671 td.DoExpandBaseInterfaces ();
1673 if (iface.Interfaces == null)
1676 foreach (var biface in iface.Interfaces) {
1677 if (spec.AddInterfaceDefined (biface)) {
1678 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1685 // Include all base type interfaces too, see ImportTypeBase for details
1687 if (base_type != null) {
1688 var td = base_type.MemberDefinition as TypeDefinition;
1690 td.DoExpandBaseInterfaces ();
1693 // Simply use base interfaces only, they are all expanded which makes
1694 // it easy to handle generic type argument propagation with single
1697 // interface IA<T> : IB<T>
1698 // interface IB<U> : IC<U>
1701 if (base_type.Interfaces != null) {
1702 foreach (var iface in base_type.Interfaces) {
1703 spec.AddInterfaceDefined (iface);
1709 public override void PrepareEmit ()
1711 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1714 foreach (var member in members) {
1715 var pbm = member as PropertyBasedMember;
1719 var pm = member as IParametersMember;
1721 var mc = member as MethodOrOperator;
1726 var p = pm.Parameters;
1730 ((ParametersCompiled) p).ResolveDefaultValues (member);
1734 var c = member as Const;
1739 base.PrepareEmit ();
1743 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1745 public override bool CreateContainer ()
1747 if (TypeBuilder != null)
1753 if (IsPartialPart) {
1754 spec = PartialContainer.spec;
1755 TypeBuilder = PartialContainer.TypeBuilder;
1756 all_tp_builders = PartialContainer.all_tp_builders;
1757 all_type_parameters = PartialContainer.all_type_parameters;
1759 if (!CreateTypeBuilder ()) {
1765 return base.CreateContainer ();
1768 protected override void DoDefineContainer ()
1772 DoResolveTypeParameters ();
1776 // Replaces normal spec with predefined one when compiling corlib
1777 // and this type container defines predefined type
1779 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1781 // When compiling build-in types we start with two
1782 // version of same type. One is of BuiltinTypeSpec and
1783 // second one is ordinary TypeSpec. The unification
1784 // happens at later stage when we know which type
1785 // really matches the builtin type signature. However
1786 // that means TypeSpec create during CreateType of this
1787 // type has to be replaced with builtin one
1789 spec.SetMetaInfo (TypeBuilder);
1790 spec.MemberCache = this.spec.MemberCache;
1791 spec.DeclaringType = this.spec.DeclaringType;
1794 current_type = null;
1797 public override void RemoveContainer (TypeContainer cont)
1799 base.RemoveContainer (cont);
1800 Members.Remove (cont);
1801 Cache.Remove (cont.MemberName.Basename);
1804 protected virtual bool DoResolveTypeParameters ()
1806 var tparams = MemberName.TypeParameters;
1807 if (tparams == null)
1810 var base_context = new BaseContext (this);
1811 for (int i = 0; i < tparams.Count; ++i) {
1812 var tp = tparams[i];
1814 if (!tp.ResolveConstraints (base_context)) {
1819 if (IsPartialPart) {
1820 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1822 tp.Create (spec, this);
1825 if (tp.OptAttributes != null) {
1826 if (pc_tp.OptAttributes == null)
1827 pc_tp.OptAttributes = tp.OptAttributes;
1829 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1834 if (IsPartialPart) {
1835 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1841 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1843 if (InTransit != null)
1848 if (base_type != null) {
1849 var ptc = base_type.MemberDefinition as TypeDefinition;
1850 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1854 if (iface_exprs != null) {
1855 foreach (var iface in iface_exprs) {
1856 // the interface might not have been resolved, prevents a crash, see #442144
1859 var ptc = iface.MemberDefinition as Interface;
1860 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1865 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1873 /// Populates our TypeBuilder with fields and methods
1875 public sealed override bool Define ()
1877 if (members_defined)
1878 return members_defined_ok;
1880 members_defined_ok = DoDefineMembers ();
1881 members_defined = true;
1885 return members_defined_ok;
1888 protected virtual bool DoDefineMembers ()
1890 Debug.Assert (!IsPartialPart);
1892 if (iface_exprs != null) {
1893 foreach (var iface_type in iface_exprs) {
1894 if (iface_type == null)
1897 // Ensure the base is always setup
1898 var compiled_iface = iface_type.MemberDefinition as Interface;
1899 if (compiled_iface != null)
1900 compiled_iface.Define ();
1902 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1903 if (oa != null && !IsObsolete)
1904 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1906 if (iface_type.Arity > 0) {
1907 // TODO: passing `this' is wrong, should be base type iface instead
1908 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1910 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1911 Report.Error (1966, Location,
1912 "`{0}': cannot implement a dynamic interface `{1}'",
1913 GetSignatureForError (), iface_type.GetSignatureForError ());
1918 if (iface_type.IsGenericOrParentIsGeneric) {
1919 foreach (var prev_iface in iface_exprs) {
1920 if (prev_iface == iface_type || prev_iface == null)
1923 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1926 Report.Error (695, Location,
1927 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1928 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1933 if (Kind == MemberKind.Interface) {
1934 foreach (var iface in spec.Interfaces) {
1935 MemberCache.AddInterface (iface);
1940 if (base_type != null) {
1942 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1944 if (base_type_expr != null) {
1945 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1946 if (obsolete_attr != null && !IsObsolete)
1947 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1949 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1950 Report.Error (698, base_type_expr.Location,
1951 "A generic type cannot derive from `{0}' because it is an attribute class",
1952 base_type.GetSignatureForError ());
1956 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1957 if (baseContainer != null) {
1958 baseContainer.Define ();
1961 // It can trigger define of this type (for generic types only)
1963 if (HasMembersDefined)
1968 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1969 pending = PendingImplementation.GetPendingImplementations (this);
1972 var count = members.Count;
1973 for (int i = 0; i < count; ++i) {
1974 var mc = members[i] as InterfaceMemberBase;
1975 if (mc == null || !mc.IsExplicitImpl)
1980 } catch (Exception e) {
1981 throw new InternalErrorException (mc, e);
1985 for (int i = 0; i < count; ++i) {
1986 var mc = members[i] as InterfaceMemberBase;
1987 if (mc != null && mc.IsExplicitImpl)
1990 if (members[i] is TypeContainer)
1994 members[i].Define ();
1995 } catch (Exception e) {
1996 throw new InternalErrorException (members[i], e);
2001 CheckPairedOperators ();
2004 if (requires_delayed_unmanagedtype_check) {
2005 requires_delayed_unmanagedtype_check = false;
2006 foreach (var member in members) {
2007 var f = member as Field;
2008 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2009 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2013 ComputeIndexerName();
2015 if (HasEquals && !HasGetHashCode) {
2016 Report.Warning (659, 3, Location,
2017 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2020 if (Kind == MemberKind.Interface && iface_exprs != null) {
2021 MemberCache.RemoveHiddenMembers (spec);
2027 void ComputeIndexerName ()
2029 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2030 if (indexers == null)
2033 string class_indexer_name = null;
2036 // Check normal indexers for consistent name, explicit interface implementation
2037 // indexers are ignored
2039 foreach (var indexer in indexers) {
2041 // FindMembers can return unfiltered full hierarchy names
2043 if (indexer.DeclaringType != spec)
2046 has_normal_indexers = true;
2048 if (class_indexer_name == null) {
2049 indexer_name = class_indexer_name = indexer.Name;
2053 if (indexer.Name != class_indexer_name)
2054 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2055 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2059 void EmitIndexerName ()
2061 if (!has_normal_indexers)
2064 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2068 var encoder = new AttributeEncoder ();
2069 encoder.Encode (GetAttributeDefaultMember ());
2070 encoder.EncodeEmptyNamedArguments ();
2072 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2075 public override void VerifyMembers ()
2078 // Check for internal or private fields that were never assigned
2080 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2081 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2082 foreach (var member in members) {
2083 if (member is Event) {
2085 // An event can be assigned from same class only, report
2086 // this warning for all accessibility modes
2088 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2089 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2094 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2095 if (is_type_exposed)
2098 member.SetIsUsed ();
2101 var f = member as Field;
2105 if (!member.IsUsed) {
2106 if (!PartialContainer.HasStructLayout) {
2107 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2108 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2110 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2111 member.GetSignatureForError ());
2118 if ((f.caching_flags & Flags.IsAssigned) != 0)
2122 // Only report 649 on level 4
2124 if (Compiler.Settings.WarningLevel < 4)
2128 // Don't be pedantic when type requires specific layout
2130 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2133 Constant c = New.Constantify (f.MemberType, f.Location);
2136 value = c.GetValueAsLiteral ();
2137 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2144 value = " `" + value + "'";
2146 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2147 f.GetSignatureForError (), value);
2151 base.VerifyMembers ();
2154 public override void Emit ()
2156 if (OptAttributes != null)
2157 OptAttributes.Emit ();
2159 if (!IsCompilerGenerated) {
2161 MemberSpec candidate;
2162 bool overrides = false;
2163 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2164 if (conflict_symbol == null && candidate == null) {
2165 if ((ModFlags & Modifiers.NEW) != 0)
2166 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2167 GetSignatureForError ());
2169 if ((ModFlags & Modifiers.NEW) == 0) {
2170 if (candidate == null)
2171 candidate = conflict_symbol;
2173 Report.SymbolRelatedToPreviousError (candidate);
2174 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2175 GetSignatureForError (), candidate.GetSignatureForError ());
2180 // Run constraints check on all possible generic types
2181 if (base_type != null && base_type_expr != null) {
2182 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2185 if (iface_exprs != null) {
2186 foreach (var iface_type in iface_exprs) {
2187 if (iface_type == null)
2190 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2195 if (all_tp_builders != null) {
2196 int current_starts_index = CurrentTypeParametersStartIndex;
2197 for (int i = 0; i < all_tp_builders.Length; i++) {
2198 if (i < current_starts_index) {
2199 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2201 var tp = CurrentTypeParameters [i - current_starts_index];
2202 tp.CheckGenericConstraints (!IsObsolete);
2208 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2209 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2212 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2213 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2218 for (int i = 0; i < members.Count; i++) {
2220 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2227 CheckAttributeClsCompliance ();
2229 if (pending != null)
2230 pending.VerifyPendingMethods ();
2234 void CheckAttributeClsCompliance ()
2236 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2239 foreach (var m in members) {
2240 var c = m as Constructor;
2244 if (c.HasCompliantArgs)
2248 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2251 public sealed override void EmitContainer ()
2253 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2259 public override void CloseContainer ()
2261 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2264 // Close base type container first to avoid TypeLoadException
2265 if (spec.BaseType != null) {
2266 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2267 if (btype != null) {
2268 btype.CloseContainer ();
2270 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2276 caching_flags |= Flags.CloseTypeCreated;
2277 TypeBuilder.CreateType ();
2278 } catch (TypeLoadException) {
2280 // This is fine, the code still created the type
2282 } catch (Exception e) {
2283 throw new InternalErrorException (this, e);
2286 base.CloseContainer ();
2289 initialized_fields = null;
2290 initialized_static_fields = null;
2292 OptAttributes = null;
2296 // Performs the validation on a Method's modifiers (properties have
2297 // the same properties).
2299 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2301 public bool MethodModifiersValid (MemberCore mc)
2303 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2304 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2306 var flags = mc.ModFlags;
2309 // At most one of static, virtual or override
2311 if ((flags & Modifiers.STATIC) != 0){
2312 if ((flags & vao) != 0){
2313 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2314 mc.GetSignatureForError ());
2319 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2320 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2321 mc.GetSignatureForError ());
2326 // If the declaration includes the abstract modifier, then the
2327 // declaration does not include static, virtual or extern
2329 if ((flags & Modifiers.ABSTRACT) != 0){
2330 if ((flags & Modifiers.EXTERN) != 0){
2332 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2336 if ((flags & Modifiers.SEALED) != 0) {
2337 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2341 if ((flags & Modifiers.VIRTUAL) != 0){
2342 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2346 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2347 Report.SymbolRelatedToPreviousError (this);
2348 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2349 mc.GetSignatureForError (), GetSignatureForError ());
2354 if ((flags & Modifiers.PRIVATE) != 0){
2355 if ((flags & vao) != 0){
2356 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2361 if ((flags & Modifiers.SEALED) != 0){
2362 if ((flags & Modifiers.OVERRIDE) == 0){
2363 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2371 protected override bool VerifyClsCompliance ()
2373 if (!base.VerifyClsCompliance ())
2376 // Check all container names for user classes
2377 if (Kind != MemberKind.Delegate)
2378 MemberCache.VerifyClsCompliance (Definition, Report);
2380 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2381 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2382 GetSignatureForError (), BaseType.GetSignatureForError ());
2388 /// Performs checks for an explicit interface implementation. First it
2389 /// checks whether the `interface_type' is a base inteface implementation.
2390 /// Then it checks whether `name' exists in the interface type.
2392 public bool VerifyImplements (InterfaceMemberBase mb)
2394 var ifaces = PartialContainer.Interfaces;
2395 if (ifaces != null) {
2396 foreach (TypeSpec t in ifaces){
2397 if (t == mb.InterfaceType)
2400 var expanded_base = t.Interfaces;
2401 if (expanded_base == null)
2404 foreach (var bt in expanded_base) {
2405 if (bt == mb.InterfaceType)
2411 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2412 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2413 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2418 // Used for visiblity checks to tests whether this definition shares
2419 // base type baseType, it does member-definition search
2421 public bool IsBaseTypeDefinition (TypeSpec baseType)
2423 // RootContext check
2424 if (TypeBuilder == null)
2429 if (type.MemberDefinition == baseType.MemberDefinition)
2432 type = type.BaseType;
2433 } while (type != null);
2438 public override bool IsClsComplianceRequired ()
2441 return PartialContainer.IsClsComplianceRequired ();
2443 return base.IsClsComplianceRequired ();
2446 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2448 return Module.DeclaringAssembly == assembly;
2451 public virtual bool IsUnmanagedType ()
2456 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2458 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2462 // Public function used to locate types.
2464 // Returns: Type or null if they type can not be found.
2466 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2468 FullNamedExpression e;
2469 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2475 var tp = CurrentTypeParameters;
2477 TypeParameter tparam = tp.Find (name);
2479 e = new TypeParameterExpr (tparam, Location.Null);
2484 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2486 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2487 e = new TypeExpression (t, Location.Null);
2489 var errors = Compiler.Report.Errors;
2490 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2492 // TODO: LookupNamespaceOrType does more than just lookup. The result
2493 // cannot be cached or the error reporting won't happen
2494 if (errors != Compiler.Report.Errors)
2499 // TODO MemberCache: How to cache arity stuff ?
2500 if (arity == 0 && mode == LookupMode.Normal)
2506 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2508 // Has any nested type
2509 // Does not work, because base type can have
2510 //if (PartialContainer.Types == null)
2513 var container = PartialContainer.CurrentType;
2514 return MemberCache.FindNestedType (container, name, arity);
2517 public void Mark_HasEquals ()
2519 cached_method |= CachedMethods.Equals;
2522 public void Mark_HasGetHashCode ()
2524 cached_method |= CachedMethods.GetHashCode;
2527 public override void WriteDebugSymbol (MonoSymbolFile file)
2532 foreach (var m in members) {
2533 m.WriteDebugSymbol (file);
2538 /// Method container contains Equals method
2540 public bool HasEquals {
2542 return (cached_method & CachedMethods.Equals) != 0;
2547 /// Method container contains GetHashCode method
2549 public bool HasGetHashCode {
2551 return (cached_method & CachedMethods.GetHashCode) != 0;
2555 public bool HasStaticFieldInitializer {
2557 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2561 cached_method |= CachedMethods.HasStaticFieldInitializer;
2563 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2567 public override string DocCommentHeader {
2568 get { return "T:"; }
2572 public abstract class ClassOrStruct : TypeDefinition
2574 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2576 SecurityType declarative_security;
2577 protected Constructor generated_primary_constructor;
2579 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2580 : base (parent, name, attrs, kind)
2584 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2586 protected override TypeAttributes TypeAttr {
2588 TypeAttributes ta = base.TypeAttr;
2589 if (!has_static_constructor)
2590 ta |= TypeAttributes.BeforeFieldInit;
2592 if (Kind == MemberKind.Class) {
2593 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2595 ta |= StaticClassAttribute;
2597 ta |= TypeAttributes.SequentialLayout;
2604 public override void AddNameToContainer (MemberCore symbol, string name)
2606 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2607 if (symbol is TypeParameter) {
2608 Report.Error (694, symbol.Location,
2609 "Type parameter `{0}' has same name as containing type, or method",
2610 symbol.GetSignatureForError ());
2614 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2615 if (imb == null || !imb.IsExplicitImpl) {
2616 Report.SymbolRelatedToPreviousError (this);
2617 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2618 symbol.GetSignatureForError ());
2623 base.AddNameToContainer (symbol, name);
2626 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2628 if (a.IsValidSecurityAttribute ()) {
2629 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2633 if (a.Type == pa.StructLayout) {
2634 PartialContainer.HasStructLayout = true;
2635 if (a.IsExplicitLayoutKind ())
2636 PartialContainer.HasExplicitLayout = true;
2639 if (a.Type == pa.Dynamic) {
2640 a.Error_MisusedDynamicAttribute ();
2644 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2648 /// Defines the default constructors
2650 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2652 // The default instance constructor is public
2653 // If the class is abstract, the default constructor is protected
2654 // The default static constructor is private
2657 ParametersCompiled parameters = null;
2659 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2660 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2662 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2663 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2666 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2667 if (Kind == MemberKind.Class)
2668 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2670 if (PrimaryConstructorParameters != null && !is_static) {
2671 c.IsPrimaryConstructor = true;
2672 c.caching_flags |= Flags.MethodOverloadsExist;
2675 AddConstructor (c, true);
2676 if (PrimaryConstructorBlock == null) {
2677 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2678 IsCompilerGenerated = true
2681 c.Block = PrimaryConstructorBlock;
2687 protected override bool DoDefineMembers ()
2689 CheckProtectedModifier ();
2691 if (PrimaryConstructorParameters != null) {
2693 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2694 if (p.Name == MemberName.Name) {
2695 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2696 GetSignatureForError ());
2699 if (CurrentTypeParameters != null) {
2700 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2701 var tp = CurrentTypeParameters [i];
2702 if (p.Name == tp.Name) {
2703 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2704 GetSignatureForError (), p.GetSignatureForError ());
2711 base.DoDefineMembers ();
2716 public override void Emit ()
2718 if (!has_static_constructor && HasStaticFieldInitializer) {
2719 var c = DefineDefaultConstructor (true);
2725 if (declarative_security != null) {
2726 foreach (var de in declarative_security) {
2728 TypeBuilder.__AddDeclarativeSecurity (de);
2730 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2738 public sealed class Class : ClassOrStruct
2740 const Modifiers AllowedModifiers =
2743 Modifiers.PROTECTED |
2744 Modifiers.INTERNAL |
2746 Modifiers.ABSTRACT |
2751 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2752 : base (parent, name, attrs, MemberKind.Class)
2754 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2755 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2756 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2759 public override void Accept (StructuralVisitor visitor)
2761 visitor.Visit (this);
2764 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2766 var pmn = MemberName;
2767 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2768 Report.Error (537, Location,
2769 "The class System.Object cannot have a base class or implement an interface.");
2771 base.SetBaseTypes (baseTypes);
2774 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2776 if (a.Type == pa.AttributeUsage) {
2777 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2778 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2782 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2783 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2787 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2788 a.Error_MissingGuidAttribute ();
2792 if (a.Type == pa.Extension) {
2793 a.Error_MisusedExtensionAttribute ();
2797 if (a.Type.IsConditionallyExcluded (this))
2800 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2803 public override AttributeTargets AttributeTargets {
2805 return AttributeTargets.Class;
2809 protected override bool DoDefineMembers ()
2811 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2812 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2815 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2816 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2820 if (PrimaryConstructorParameters != null) {
2821 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2822 PrimaryConstructorParameters = null;
2825 foreach (var m in Members) {
2826 if (m is Operator) {
2827 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2831 if (m is Destructor) {
2832 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2837 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2841 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2844 if (m is Constructor) {
2845 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2849 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2852 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2853 generated_primary_constructor = DefineDefaultConstructor (false);
2856 return base.DoDefineMembers ();
2859 public override void Emit ()
2863 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2864 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2866 if (base_type != null && base_type.HasDynamicElement) {
2867 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2871 public override void GetCompletionStartingWith (string prefix, List<string> results)
2873 base.GetCompletionStartingWith (prefix, results);
2876 while (bt != null) {
2877 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2882 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2884 var ifaces = base.ResolveBaseTypes (out base_class);
2886 if (base_class == null) {
2887 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2888 base_type = Compiler.BuiltinTypes.Object;
2890 if (base_type.IsGenericParameter){
2891 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2892 GetSignatureForError (), base_type.GetSignatureForError ());
2893 } else if (base_type.IsStatic) {
2894 Report.SymbolRelatedToPreviousError (base_type);
2895 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2896 GetSignatureForError (), base_type.GetSignatureForError ());
2897 } else if (base_type.IsSealed) {
2898 Report.SymbolRelatedToPreviousError (base_type);
2899 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2900 GetSignatureForError (), base_type.GetSignatureForError ());
2901 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2902 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2903 GetSignatureForError (), base_type.GetSignatureForError ());
2906 switch (base_type.BuiltinType) {
2907 case BuiltinTypeSpec.Type.Enum:
2908 case BuiltinTypeSpec.Type.ValueType:
2909 case BuiltinTypeSpec.Type.MulticastDelegate:
2910 case BuiltinTypeSpec.Type.Delegate:
2911 case BuiltinTypeSpec.Type.Array:
2912 if (!(spec is BuiltinTypeSpec)) {
2913 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2914 GetSignatureForError (), base_type.GetSignatureForError ());
2916 base_type = Compiler.BuiltinTypes.Object;
2921 if (!IsAccessibleAs (base_type)) {
2922 Report.SymbolRelatedToPreviousError (base_type);
2923 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2924 base_type.GetSignatureForError (), GetSignatureForError ());
2928 if (PartialContainer.IsStatic && ifaces != null) {
2929 foreach (var t in ifaces)
2930 Report.SymbolRelatedToPreviousError (t);
2931 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2937 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2938 /// Valid only for attribute classes.
2939 public override string[] ConditionalConditions ()
2941 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2944 caching_flags &= ~Flags.Excluded_Undetected;
2946 if (OptAttributes == null)
2949 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2953 string[] conditions = new string[attrs.Length];
2954 for (int i = 0; i < conditions.Length; ++i)
2955 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2957 caching_flags |= Flags.Excluded;
2962 public sealed class Struct : ClassOrStruct
2964 bool is_unmanaged, has_unmanaged_check_done;
2968 // Modifiers allowed in a struct declaration
2970 const Modifiers AllowedModifiers =
2973 Modifiers.PROTECTED |
2974 Modifiers.INTERNAL |
2978 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2979 : base (parent, name, attrs, MemberKind.Struct)
2981 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2982 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2983 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2986 public override AttributeTargets AttributeTargets {
2988 return AttributeTargets.Struct;
2992 public override void Accept (StructuralVisitor visitor)
2994 visitor.Visit (this);
2997 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2999 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3002 // When struct constains fixed fixed and struct layout has explicitly
3003 // set CharSet, its value has to be propagated to compiler generated
3006 if (a.Type == pa.StructLayout) {
3007 var value = a.GetNamedValue ("CharSet");
3011 for (int i = 0; i < Members.Count; ++i) {
3012 FixedField ff = Members [i] as FixedField;
3016 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3021 bool CheckStructCycles ()
3027 foreach (var member in Members) {
3028 var field = member as Field;
3032 TypeSpec ftype = field.Spec.MemberType;
3033 if (!ftype.IsStruct)
3036 if (ftype is BuiltinTypeSpec)
3039 foreach (var targ in ftype.TypeArguments) {
3040 if (!CheckFieldTypeCycle (targ)) {
3041 Report.Error (523, field.Location,
3042 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3043 field.GetSignatureForError (), ftype.GetSignatureForError ());
3049 // Static fields of exactly same type are allowed
3051 if (field.IsStatic && ftype == CurrentType)
3054 if (!CheckFieldTypeCycle (ftype)) {
3055 Report.Error (523, field.Location,
3056 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3057 field.GetSignatureForError (), ftype.GetSignatureForError ());
3066 static bool CheckFieldTypeCycle (TypeSpec ts)
3068 var fts = ts.MemberDefinition as Struct;
3072 return fts.CheckStructCycles ();
3075 protected override bool DoDefineMembers ()
3077 var res = base.DoDefineMembers ();
3079 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3080 generated_primary_constructor = DefineDefaultConstructor (false);
3081 generated_primary_constructor.Define ();
3087 public override void Emit ()
3089 CheckStructCycles ();
3094 bool HasUserDefaultConstructor ()
3096 foreach (var m in PartialContainer.Members) {
3097 var c = m as Constructor;
3101 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3108 public override bool IsUnmanagedType ()
3110 if (has_unmanaged_check_done)
3111 return is_unmanaged;
3113 if (requires_delayed_unmanagedtype_check)
3116 var parent_def = Parent.PartialContainer;
3117 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3118 has_unmanaged_check_done = true;
3122 if (first_nonstatic_field != null) {
3123 requires_delayed_unmanagedtype_check = true;
3125 foreach (var member in Members) {
3126 var f = member as Field;
3133 // It can happen when recursive unmanaged types are defined
3134 // struct S { S* s; }
3135 TypeSpec mt = f.MemberType;
3143 has_unmanaged_check_done = true;
3147 has_unmanaged_check_done = true;
3150 is_unmanaged = true;
3154 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3156 var ifaces = base.ResolveBaseTypes (out base_class);
3157 base_type = Compiler.BuiltinTypes.ValueType;
3165 public sealed class Interface : TypeDefinition {
3168 /// Modifiers allowed in a class declaration
3170 const Modifiers AllowedModifiers =
3173 Modifiers.PROTECTED |
3174 Modifiers.INTERNAL |
3178 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3179 : base (parent, name, attrs, MemberKind.Interface)
3181 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3183 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3184 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3189 public override AttributeTargets AttributeTargets {
3191 return AttributeTargets.Interface;
3195 protected override TypeAttributes TypeAttr {
3197 const TypeAttributes DefaultTypeAttributes =
3198 TypeAttributes.AutoLayout |
3199 TypeAttributes.Abstract |
3200 TypeAttributes.Interface;
3202 return base.TypeAttr | DefaultTypeAttributes;
3208 public override void Accept (StructuralVisitor visitor)
3210 visitor.Visit (this);
3213 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3215 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3216 a.Error_MissingGuidAttribute ();
3220 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3223 protected override bool VerifyClsCompliance ()
3225 if (!base.VerifyClsCompliance ())
3228 if (iface_exprs != null) {
3229 foreach (var iface in iface_exprs) {
3230 if (iface.IsCLSCompliant ())
3233 Report.SymbolRelatedToPreviousError (iface);
3234 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3235 GetSignatureForError (), iface.GetSignatureForError ());
3243 public abstract class InterfaceMemberBase : MemberBase
3246 // Common modifiers allowed in a class declaration
3248 protected const Modifiers AllowedModifiersClass =
3251 Modifiers.PROTECTED |
3252 Modifiers.INTERNAL |
3257 Modifiers.OVERRIDE |
3258 Modifiers.ABSTRACT |
3263 // Common modifiers allowed in a struct declaration
3265 protected const Modifiers AllowedModifiersStruct =
3268 Modifiers.PROTECTED |
3269 Modifiers.INTERNAL |
3272 Modifiers.OVERRIDE |
3277 // Common modifiers allowed in a interface declaration
3279 protected const Modifiers AllowedModifiersInterface =
3284 // Whether this is an interface member.
3286 public bool IsInterface;
3289 // If true, this is an explicit interface implementation
3291 public readonly bool IsExplicitImpl;
3293 protected bool is_external_implementation;
3296 // The interface type we are explicitly implementing
3298 public TypeSpec InterfaceType;
3301 // The method we're overriding if this is an override method.
3303 protected MethodSpec base_method;
3305 readonly Modifiers explicit_mod_flags;
3306 public MethodAttributes flags;
3308 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3309 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3311 IsInterface = parent.Kind == MemberKind.Interface;
3312 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3313 explicit_mod_flags = mod;
3316 public abstract Variance ExpectedMemberTypeVariance { get; }
3318 protected override bool CheckBase ()
3320 if (!base.CheckBase ())
3323 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3324 CheckForDuplications ();
3329 // For System.Object only
3330 if (Parent.BaseType == null)
3333 MemberSpec candidate;
3334 bool overrides = false;
3335 var base_member = FindBaseMember (out candidate, ref overrides);
3337 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3338 if (base_member == null) {
3339 if (candidate == null) {
3340 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3341 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3342 "object.Finalize()");
3344 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3345 GetSignatureForError (), SimpleName.GetMemberType (this));
3348 Report.SymbolRelatedToPreviousError (candidate);
3350 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3351 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3352 else if (this is PropertyBase)
3353 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3354 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3356 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3357 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3364 // Handles ambiguous overrides
3366 if (candidate != null) {
3367 Report.SymbolRelatedToPreviousError (candidate);
3368 Report.SymbolRelatedToPreviousError (base_member);
3370 // Get member definition for error reporting
3371 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3372 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3374 Report.Error (462, Location,
3375 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3376 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3379 if (!CheckOverrideAgainstBase (base_member))
3382 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3384 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3385 Report.SymbolRelatedToPreviousError (base_member);
3386 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3387 GetSignatureForError (), base_member.GetSignatureForError ());
3390 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3391 Report.SymbolRelatedToPreviousError (base_member);
3392 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3393 GetSignatureForError (), base_member.GetSignatureForError ());
3397 base_method = base_member as MethodSpec;
3401 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3402 base_member = candidate;
3404 if (base_member == null) {
3405 if ((ModFlags & Modifiers.NEW) != 0) {
3406 if (base_member == null) {
3407 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3408 GetSignatureForError ());
3412 if ((ModFlags & Modifiers.NEW) == 0) {
3413 ModFlags |= Modifiers.NEW;
3414 if (!IsCompilerGenerated) {
3415 Report.SymbolRelatedToPreviousError (base_member);
3416 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3417 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",
3418 GetSignatureForError (), base_member.GetSignatureForError ());
3420 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3421 GetSignatureForError (), base_member.GetSignatureForError ());
3426 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3427 Report.SymbolRelatedToPreviousError (base_member);
3428 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3429 GetSignatureForError (), base_member.GetSignatureForError ());
3436 protected virtual bool CheckForDuplications ()
3438 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3442 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3443 // that have been defined.
3445 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3449 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3450 Report.SymbolRelatedToPreviousError (base_member);
3451 Report.Error (506, Location,
3452 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3453 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3457 // Now we check that the overriden method is not final
3458 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3459 Report.SymbolRelatedToPreviousError (base_member);
3460 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3461 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3465 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3466 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3467 Report.SymbolRelatedToPreviousError (base_member);
3468 if (this is PropertyBasedMember) {
3469 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3470 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3472 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3473 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3481 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3483 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3484 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3486 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3488 // It must be at least "protected"
3490 if ((thisp & Modifiers.PROTECTED) == 0) {
3495 // when overriding protected internal, the method can be declared
3496 // protected internal only within the same assembly or assembly
3497 // which has InternalsVisibleTo
3499 if ((thisp & Modifiers.INTERNAL) != 0) {
3500 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3504 // protected overriding protected internal inside same assembly
3505 // requires internal modifier as well
3507 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3514 return thisp == base_classp;
3517 public override bool Define ()
3520 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3521 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3523 flags = MethodAttributes.Public |
3524 MethodAttributes.Abstract |
3525 MethodAttributes.HideBySig |
3526 MethodAttributes.NewSlot |
3527 MethodAttributes.Virtual;
3529 Parent.PartialContainer.MethodModifiersValid (this);
3531 flags = ModifiersExtensions.MethodAttr (ModFlags);
3534 if (IsExplicitImpl) {
3535 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3536 if (InterfaceType == null)
3539 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3540 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3541 GetSignatureForError ());
3544 if (!InterfaceType.IsInterface) {
3545 Report.SymbolRelatedToPreviousError (InterfaceType);
3546 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3547 InterfaceType.GetSignatureForError ());
3549 Parent.PartialContainer.VerifyImplements (this);
3552 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3554 allowed_explicit |= Modifiers.ASYNC;
3556 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3559 return base.Define ();
3562 protected bool DefineParameters (ParametersCompiled parameters)
3564 if (!parameters.Resolve (this))
3568 for (int i = 0; i < parameters.Count; ++i) {
3569 Parameter p = parameters [i];
3571 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3572 p.Warning_UselessOptionalParameter (Report);
3574 if (p.CheckAccessibility (this))
3577 TypeSpec t = parameters.Types [i];
3578 Report.SymbolRelatedToPreviousError (t);
3579 if (this is Indexer)
3580 Report.Error (55, Location,
3581 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3582 t.GetSignatureForError (), GetSignatureForError ());
3583 else if (this is Operator)
3584 Report.Error (57, Location,
3585 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3586 t.GetSignatureForError (), GetSignatureForError ());
3588 Report.Error (51, Location,
3589 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3590 t.GetSignatureForError (), GetSignatureForError ());
3596 protected override void DoMemberTypeDependentChecks ()
3598 base.DoMemberTypeDependentChecks ();
3600 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3603 public override void Emit()
3605 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3606 // We are more strict than csc and report this as an error because SRE does not allow emit that
3607 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3608 if (this is Constructor) {
3609 Report.Warning (824, 1, Location,
3610 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3612 Report.Warning (626, 1, Location,
3613 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3614 GetSignatureForError ());
3621 public override bool EnableOverloadChecks (MemberCore overload)
3624 // Two members can differ in their explicit interface
3625 // type parameter only
3627 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3628 if (imb != null && imb.IsExplicitImpl) {
3629 if (IsExplicitImpl) {
3630 caching_flags |= Flags.MethodOverloadsExist;
3635 return IsExplicitImpl;
3638 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3640 var base_modifiers = base_member.Modifiers;
3642 // Remove internal modifier from types which are not internally accessible
3643 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3644 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3645 base_modifiers = Modifiers.PROTECTED;
3647 Report.SymbolRelatedToPreviousError (base_member);
3648 Report.Error (507, member.Location,
3649 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3650 member.GetSignatureForError (),
3651 ModifiersExtensions.AccessibilityName (base_modifiers),
3652 base_member.GetSignatureForError ());
3655 protected void Error_StaticReturnType ()
3657 Report.Error (722, Location,
3658 "`{0}': static types cannot be used as return types",
3659 MemberType.GetSignatureForError ());
3663 /// Gets base method and its return type
3665 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3667 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3671 // The "short" name of this property / indexer / event. This is the
3672 // name without the explicit interface.
3674 public string ShortName {
3675 get { return MemberName.Name; }
3679 // Returns full metadata method name
3681 public string GetFullName (MemberName name)
3683 return GetFullName (name.Name);
3686 public string GetFullName (string name)
3688 if (!IsExplicitImpl)
3692 // When dealing with explicit members a full interface type
3693 // name is added to member name to avoid possible name conflicts
3695 // We use CSharpName which gets us full name with benefit of
3696 // replacing predefined names which saves some space and name
3699 return InterfaceType.GetSignatureForError () + "." + name;
3702 public override string GetSignatureForDocumentation ()
3705 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3707 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3710 public override bool IsUsed
3712 get { return IsExplicitImpl || base.IsUsed; }
3715 public override void SetConstraints (List<Constraints> constraints_list)
3717 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3718 Report.Error (460, Location,
3719 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3720 GetSignatureForError ());
3723 base.SetConstraints (constraints_list);
3727 public abstract class MemberBase : MemberCore
3729 protected FullNamedExpression type_expr;
3730 protected TypeSpec member_type;
3731 public new TypeDefinition Parent;
3733 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3734 : base (parent, name, attrs)
3736 this.Parent = parent;
3737 this.type_expr = type;
3739 if (name != MemberName.Null)
3740 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3745 public TypeSpec MemberType {
3751 public FullNamedExpression TypeExpression {
3760 // Main member define entry
3762 public override bool Define ()
3764 DoMemberTypeIndependentChecks ();
3767 // Returns false only when type resolution failed
3769 if (!ResolveMemberType ())
3772 DoMemberTypeDependentChecks ();
3777 // Any type_name independent checks
3779 protected virtual void DoMemberTypeIndependentChecks ()
3781 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3782 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3783 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3784 GetSignatureForError (), Parent.GetSignatureForError ());
3789 // Any type_name dependent checks
3791 protected virtual void DoMemberTypeDependentChecks ()
3793 // verify accessibility
3794 if (!IsAccessibleAs (MemberType)) {
3795 Report.SymbolRelatedToPreviousError (MemberType);
3796 if (this is Property)
3797 Report.Error (53, Location,
3798 "Inconsistent accessibility: property type `" +
3799 MemberType.GetSignatureForError () + "' is less " +
3800 "accessible than property `" + GetSignatureForError () + "'");
3801 else if (this is Indexer)
3802 Report.Error (54, Location,
3803 "Inconsistent accessibility: indexer return type `" +
3804 MemberType.GetSignatureForError () + "' is less " +
3805 "accessible than indexer `" + GetSignatureForError () + "'");
3806 else if (this is MethodCore) {
3807 if (this is Operator)
3808 Report.Error (56, Location,
3809 "Inconsistent accessibility: return type `" +
3810 MemberType.GetSignatureForError () + "' is less " +
3811 "accessible than operator `" + GetSignatureForError () + "'");
3813 Report.Error (50, Location,
3814 "Inconsistent accessibility: return type `" +
3815 MemberType.GetSignatureForError () + "' is less " +
3816 "accessible than method `" + GetSignatureForError () + "'");
3817 } else if (this is Event) {
3818 Report.Error (7025, Location,
3819 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3820 MemberType.GetSignatureForError (), GetSignatureForError ());
3822 Report.Error (52, Location,
3823 "Inconsistent accessibility: field type `" +
3824 MemberType.GetSignatureForError () + "' is less " +
3825 "accessible than field `" + GetSignatureForError () + "'");
3830 protected void IsTypePermitted ()
3832 if (MemberType.IsSpecialRuntimeType) {
3833 if (Parent is StateMachine) {
3834 Report.Error (4012, Location,
3835 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3836 MemberType.GetSignatureForError ());
3837 } else if (Parent is HoistedStoreyClass) {
3838 Report.Error (4013, Location,
3839 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3840 MemberType.GetSignatureForError ());
3842 Report.Error (610, Location,
3843 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3848 protected virtual bool CheckBase ()
3850 CheckProtectedModifier ();
3855 public override string GetSignatureForDocumentation ()
3857 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3860 protected virtual bool ResolveMemberType ()
3862 if (member_type != null)
3863 throw new InternalErrorException ("Multi-resolve");
3865 member_type = type_expr.ResolveAsType (this);
3866 return member_type != null;