2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2011 Novell, Inc
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Security;
20 using System.Security.Permissions;
22 using System.Diagnostics;
23 using Mono.CompilerServices.SymbolWriter;
26 using XmlElement = System.Object;
30 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
31 using IKVM.Reflection;
32 using IKVM.Reflection.Emit;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
42 // General types container, used as a base class for all constructs which can hold types
44 public abstract class TypeContainer : MemberCore
46 public readonly MemberKind Kind;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public int CounterAnonymousMethods { get; set; }
57 public int CounterAnonymousContainers { get; set; }
58 public int CounterSwitchTypes { get; set; }
60 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
61 : base (parent, name, attrs)
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. Used
98 public Attributes UnattachedAttributes {
102 public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
104 AddTypeContainerMember (c);
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 existing.AddPartialPart (next_part);
193 AddTypeContainerMember (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
198 AddTypeContainerMember (tc);
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 protected virtual void AddTypeContainerMember (TypeContainer tc)
218 public virtual void CloseContainer ()
220 if (containers != null) {
221 foreach (TypeContainer tc in containers) {
222 tc.CloseContainer ();
227 public virtual void CreateMetadataName (StringBuilder sb)
229 if (Parent != null && Parent.MemberName != null)
230 Parent.CreateMetadataName (sb);
232 MemberName.CreateMetadataName (sb);
235 public virtual bool CreateContainer ()
237 if (containers != null) {
238 foreach (TypeContainer tc in containers) {
239 tc.CreateContainer ();
246 public override bool Define ()
248 if (containers != null) {
249 foreach (TypeContainer tc in containers) {
254 // Release cache used by parser only
255 if (Module.Evaluator == null) {
256 defined_names = null;
258 defined_names.Clear ();
264 public virtual void PrepareEmit ()
266 if (containers != null) {
267 foreach (var t in containers) {
270 } catch (Exception e) {
271 if (MemberName == MemberName.Null)
274 throw new InternalErrorException (t, e);
280 public virtual bool DefineContainer ()
287 DoDefineContainer ();
289 if (containers != null) {
290 foreach (TypeContainer tc in containers) {
292 tc.DefineContainer ();
293 } catch (Exception e) {
294 if (MemberName == MemberName.Null)
297 throw new InternalErrorException (tc, e);
301 if (PartialContainer != null && PartialContainer != this) {
309 public virtual void ExpandBaseInterfaces ()
311 if (containers != null) {
312 foreach (TypeContainer tc in containers) {
313 tc.ExpandBaseInterfaces ();
318 protected virtual void DefineNamespace ()
320 if (containers != null) {
321 foreach (var tc in containers) {
323 tc.DefineNamespace ();
324 } catch (Exception e) {
325 throw new InternalErrorException (tc, e);
331 protected virtual void DoDefineContainer ()
335 public virtual void EmitContainer ()
337 if (containers != null) {
338 for (int i = 0; i < containers.Count; ++i)
339 containers[i].EmitContainer ();
343 protected void Error_MissingPartialModifier (MemberCore type)
345 Report.Error (260, type.Location,
346 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
347 type.GetSignatureForError ());
350 public override string GetSignatureForDocumentation ()
352 if (Parent != null && Parent.MemberName != null)
353 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
355 return MemberName.GetSignatureForDocumentation ();
358 public override string GetSignatureForError ()
360 if (Parent != null && Parent.MemberName != null)
361 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
363 return MemberName.GetSignatureForError ();
366 public virtual string GetSignatureForMetadata ()
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 (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;
538 bool members_defined;
539 bool members_defined_ok;
540 protected bool has_static_constructor;
542 private CachedMethods cached_method;
544 protected TypeSpec spec;
545 TypeSpec current_type;
547 public int DynamicSitesCounter;
548 public int AnonymousMethodsCounter;
549 public int MethodGroupsCounter;
551 static readonly string[] attribute_targets = new [] { "type" };
552 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
555 /// The pending methods that need to be implemented
556 // (interfaces or abstract methods)
558 PendingImplementation pending;
560 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
561 : base (parent, name, attrs, kind)
563 PartialContainer = this;
564 members = new List<MemberCore> ();
569 public List<FullNamedExpression> BaseTypeExpressions {
575 public override TypeSpec CurrentType {
577 if (current_type == null) {
578 if (IsGenericOrParentIsGeneric) {
580 // Switch to inflated version as it's used by all expressions
582 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
583 current_type = spec.MakeGenericType (this, targs);
593 public override TypeParameters CurrentTypeParameters {
595 return PartialContainer.MemberName.TypeParameters;
599 int CurrentTypeParametersStartIndex {
601 int total = all_tp_builders.Length;
602 if (CurrentTypeParameters != null) {
603 return total - CurrentTypeParameters.Count;
609 public virtual AssemblyDefinition DeclaringAssembly {
611 return Module.DeclaringAssembly;
615 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
617 return Module.DeclaringAssembly;
621 public TypeSpec Definition {
627 public bool HasMembersDefined {
629 return members_defined;
633 public bool HasInstanceConstructor {
635 return (caching_flags & Flags.HasInstanceConstructor) != 0;
638 caching_flags |= Flags.HasInstanceConstructor;
642 public bool HasInstanceField {
644 return (caching_flags & Flags.HasInstanceField) != 0;
647 caching_flags |= Flags.HasInstanceField;
651 // Indicated whether container has StructLayout attribute set Explicit
652 public bool HasExplicitLayout {
653 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
654 set { caching_flags |= Flags.HasExplicitLayout; }
657 public bool HasOperators {
659 return (caching_flags & Flags.HasUserOperators) != 0;
662 caching_flags |= Flags.HasUserOperators;
666 public bool HasStructLayout {
667 get { return (caching_flags & Flags.HasStructLayout) != 0; }
668 set { caching_flags |= Flags.HasStructLayout; }
671 public TypeSpec[] Interfaces {
677 public bool IsGenericOrParentIsGeneric {
679 return all_type_parameters != null;
683 public bool IsTopLevel {
685 return !(Parent is TypeDefinition);
689 public bool IsPartial {
691 return (ModFlags & Modifiers.PARTIAL) != 0;
695 bool ITypeDefinition.IsTypeForwarder {
701 bool ITypeDefinition.IsCyclicTypeForwarder {
708 // Returns true for secondary partial containers
712 return PartialContainer != this;
716 public MemberCache MemberCache {
718 return spec.MemberCache;
722 public List<MemberCore> Members {
728 string ITypeDefinition.Namespace {
731 while (p.Kind != MemberKind.Namespace)
734 return p.MemberName == null ? null : p.GetSignatureForError ();
738 public ParametersCompiled PrimaryConstructorParameters { get; set; }
740 public Arguments PrimaryConstructorBaseArguments { get; set; }
742 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
744 public TypeParameters TypeParametersAll {
746 return all_type_parameters;
750 public override string[] ValidAttributeTargets {
752 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
758 public override void Accept (StructuralVisitor visitor)
760 visitor.Visit (this);
763 public void AddMember (MemberCore symbol)
765 if (symbol.MemberName.ExplicitInterface != null) {
766 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
767 Report.Error (541, symbol.Location,
768 "`{0}': explicit interface declaration can only be declared in a class or struct",
769 symbol.GetSignatureForError ());
773 AddNameToContainer (symbol, symbol.MemberName.Name);
774 members.Add (symbol);
777 public override void AddTypeContainer (TypeContainer tc)
779 AddNameToContainer (tc, tc.MemberName.Basename);
781 base.AddTypeContainer (tc);
784 protected override void AddTypeContainerMember (TypeContainer tc)
788 if (containers == null)
789 containers = new List<TypeContainer> ();
791 base.AddTypeContainerMember (tc);
795 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
797 public virtual void AddNameToContainer (MemberCore symbol, string name)
799 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
803 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
804 PartialContainer.defined_names.Add (name, symbol);
808 if (symbol.EnableOverloadChecks (mc))
811 InterfaceMemberBase im = mc as InterfaceMemberBase;
812 if (im != null && im.IsExplicitImpl)
815 Report.SymbolRelatedToPreviousError (mc);
816 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
817 Error_MissingPartialModifier (symbol);
821 if (symbol is TypeParameter) {
822 Report.Error (692, symbol.Location,
823 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
825 Report.Error (102, symbol.Location,
826 "The type `{0}' already contains a definition for `{1}'",
827 GetSignatureForError (), name);
833 public void AddConstructor (Constructor c)
835 AddConstructor (c, false);
838 public void AddConstructor (Constructor c, bool isDefault)
840 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
842 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
844 if (is_static && c.ParameterInfo.IsEmpty) {
845 PartialContainer.has_static_constructor = true;
847 PartialContainer.HasInstanceConstructor = true;
853 public bool AddField (FieldBase field)
857 if ((field.ModFlags & Modifiers.STATIC) != 0)
860 if (!PartialContainer.HasInstanceField) {
861 PartialContainer.HasInstanceField = true;
862 PartialContainer.first_nonstatic_field = field;
866 if (Kind == MemberKind.Struct) {
867 var first_field = PartialContainer.first_nonstatic_field;
868 if (first_field.Parent != field.Parent) {
869 Report.SymbolRelatedToPreviousError (first_field.Parent);
870 Report.Warning (282, 3, field.Location,
871 "struct instance field `{0}' found in different declaration from instance field `{1}'",
872 field.GetSignatureForError (), first_field.GetSignatureForError ());
880 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
882 public void AddIndexer (Indexer i)
887 public void AddOperator (Operator op)
889 PartialContainer.HasOperators = true;
893 public void AddPartialPart (TypeDefinition part)
895 if (Kind != MemberKind.Class)
898 if (class_partial_parts == null)
899 class_partial_parts = new List<TypeDefinition> ();
901 class_partial_parts.Add (part);
904 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
906 if (a.Target == AttributeTargets.Method) {
907 foreach (var m in members) {
908 var c = m as Constructor;
912 if (c.IsPrimaryConstructor) {
913 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
918 throw new InternalErrorException ();
921 if (has_normal_indexers && a.Type == pa.DefaultMember) {
922 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
926 if (a.Type == pa.Required) {
927 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
931 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
934 public override AttributeTargets AttributeTargets {
936 throw new NotSupportedException ();
940 public TypeSpec BaseType {
942 return spec.BaseType;
946 protected virtual TypeAttributes TypeAttr {
948 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
952 public int TypeParametersCount {
954 return MemberName.Arity;
958 TypeParameterSpec[] ITypeDefinition.TypeParameters {
960 var ctp = PartialContainer.CurrentTypeParameters;
961 return ctp == null ? TypeParameterSpec.EmptyTypes : ctp.Types;
965 public string GetAttributeDefaultMember ()
967 return indexer_name ?? DefaultIndexerName;
970 public bool IsComImport {
972 if (OptAttributes == null)
975 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
979 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
982 PartialContainer.RegisterFieldForInitialization (field, expression);
984 if ((field.ModFlags & Modifiers.STATIC) != 0){
985 if (initialized_static_fields == null) {
986 HasStaticFieldInitializer = true;
987 initialized_static_fields = new List<FieldInitializer> (4);
990 initialized_static_fields.Add (expression);
992 if (Kind == MemberKind.Struct) {
993 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
994 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
995 GetSignatureForError ());
999 if (initialized_fields == null)
1000 initialized_fields = new List<FieldInitializer> (4);
1002 initialized_fields.Add (expression);
1006 public void ResolveFieldInitializers (BlockContext ec)
1008 Debug.Assert (!IsPartialPart);
1011 if (initialized_static_fields == null)
1014 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
1016 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1017 for (i = 0; i < initialized_static_fields.Count; ++i) {
1018 FieldInitializer fi = initialized_static_fields [i];
1019 ExpressionStatement s = fi.ResolveStatement (ec);
1021 s = EmptyExpressionStatement.Instance;
1022 } else if (!fi.IsSideEffectFree) {
1023 has_complex_initializer = true;
1029 for (i = 0; i < initialized_static_fields.Count; ++i) {
1030 FieldInitializer fi = initialized_static_fields [i];
1032 // Need special check to not optimize code like this
1033 // static int a = b = 5;
1034 // static int b = 0;
1036 if (!has_complex_initializer && fi.IsDefaultInitializer)
1039 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1040 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1046 if (initialized_fields == null)
1049 for (int i = 0; i < initialized_fields.Count; ++i) {
1050 FieldInitializer fi = initialized_fields [i];
1053 // Clone before resolving otherwise when field initializer is needed
1054 // in more than 1 constructor any resolve after the initial one would
1055 // only took the resolved expression which is problem for expressions
1056 // that generate extra expressions or code during Resolve phase
1058 var cloned = fi.Clone (new CloneContext ());
1060 ExpressionStatement s = fi.ResolveStatement (ec);
1062 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1067 // Field is re-initialized to its default value => removed
1069 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1072 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1073 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1074 initialized_fields [i] = (FieldInitializer) cloned;
1078 public override string DocComment {
1090 public PendingImplementation PendingImplementations {
1091 get { return pending; }
1094 internal override void GenerateDocComment (DocumentationBuilder builder)
1099 base.GenerateDocComment (builder);
1101 foreach (var member in members)
1102 member.GenerateDocComment (builder);
1105 public TypeSpec GetAttributeCoClass ()
1107 if (OptAttributes == null)
1110 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1114 return a.GetCoClassAttributeValue ();
1117 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1120 if (OptAttributes != null) {
1121 a = OptAttributes.Search (pa);
1127 return a.GetAttributeUsageAttribute ();
1130 public virtual CompilationSourceFile GetCompilationSourceFile ()
1132 TypeContainer ns = Parent;
1134 var sf = ns as CompilationSourceFile;
1142 public override string GetSignatureForMetadata ()
1144 if (Parent is TypeDefinition) {
1145 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1148 return base.GetSignatureForMetadata ();
1151 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1153 type_bases = baseTypes;
1157 /// This function computes the Base class and also the
1158 /// list of interfaces that the class or struct @c implements.
1160 /// The return value is an array (might be null) of
1161 /// interfaces implemented (as Types).
1163 /// The @base_class argument is set to the base object or null
1164 /// if this is `System.Object'.
1166 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1169 if (type_bases == null)
1172 int count = type_bases.Count;
1173 TypeSpec[] ifaces = null;
1174 var base_context = new BaseContext (this);
1175 for (int i = 0, j = 0; i < count; i++){
1176 FullNamedExpression fne = type_bases [i];
1178 var fne_resolved = fne.ResolveAsType (base_context);
1179 if (fne_resolved == null)
1182 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1183 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1184 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1185 GetSignatureForError ());
1190 base_type = fne_resolved;
1196 ifaces = new TypeSpec [count - i];
1198 if (fne_resolved.IsInterface) {
1199 for (int ii = 0; ii < j; ++ii) {
1200 if (fne_resolved == ifaces [ii]) {
1201 Report.Error (528, Location, "`{0}' is already listed in interface list",
1202 fne_resolved.GetSignatureForError ());
1207 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1208 Report.Error (61, fne.Location,
1209 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1210 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1213 Report.SymbolRelatedToPreviousError (fne_resolved);
1214 if (Kind != MemberKind.Class) {
1215 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1216 } else if (base_class != null)
1217 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1218 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1220 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1221 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1225 ifaces [j++] = fne_resolved;
1232 // Checks that some operators come in pairs:
1238 // They are matched based on the return type and the argument types
1240 void CheckPairedOperators ()
1242 bool has_equality_or_inequality = false;
1243 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1245 for (int i = 0; i < members.Count; ++i) {
1246 var o_a = members[i] as Operator;
1250 var o_type = o_a.OperatorType;
1251 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1252 has_equality_or_inequality = true;
1254 if (found_matched.Contains (o_type))
1257 var matching_type = o_a.GetMatchingOperator ();
1258 if (matching_type == Operator.OpType.TOP) {
1262 bool pair_found = false;
1263 for (int ii = 0; ii < members.Count; ++ii) {
1264 var o_b = members[ii] as Operator;
1265 if (o_b == null || o_b.OperatorType != matching_type)
1268 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1271 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1274 found_matched.Add (matching_type);
1280 Report.Error (216, o_a.Location,
1281 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1282 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1286 if (has_equality_or_inequality) {
1288 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1289 GetSignatureForError ());
1291 if (!HasGetHashCode)
1292 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1293 GetSignatureForError ());
1297 public override void CreateMetadataName (StringBuilder sb)
1299 if (Parent.MemberName != null) {
1300 Parent.CreateMetadataName (sb);
1302 if (sb.Length != 0) {
1307 sb.Append (MemberName.Basename);
1310 bool CreateTypeBuilder ()
1313 // Sets .size to 1 for structs with no instance fields
1315 int type_size = Kind == MemberKind.Struct && !HasInstanceField && !(this is StateMachine) ? 1 : 0;
1317 var parent_def = Parent as TypeDefinition;
1318 if (parent_def == null) {
1319 var sb = new StringBuilder ();
1320 CreateMetadataName (sb);
1321 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1323 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1326 if (DeclaringAssembly.Importer != null)
1327 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1329 spec.SetMetaInfo (TypeBuilder);
1330 spec.MemberCache = new MemberCache (this);
1332 TypeParameters parentAllTypeParameters = null;
1333 if (parent_def != null) {
1334 spec.DeclaringType = Parent.CurrentType;
1335 parent_def.MemberCache.AddMember (spec);
1336 parentAllTypeParameters = parent_def.all_type_parameters;
1339 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1340 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1342 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1344 if (CurrentTypeParameters != null) {
1345 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1346 CurrentTypeParameters.Define (all_tp_builders);
1353 public static string FilterNestedName (string name)
1356 // SRE API does not handle namespaces and types separately but
1357 // determine that from '.' in name. That's problematic because
1358 // dot is valid character for type name. By replacing any '.'
1359 // in name we avoid any ambiguities and never emit metadata
1360 // namespace for nested types
1362 return name.Replace ('.', '_');
1365 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1368 int parent_offset = 0;
1369 if (parentAllTypeParameters != null) {
1370 if (CurrentTypeParameters == null) {
1371 all_type_parameters = parentAllTypeParameters;
1372 return parentAllTypeParameters.GetAllNames ();
1375 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1376 all_type_parameters = new TypeParameters (names.Length);
1377 all_type_parameters.Add (parentAllTypeParameters);
1379 parent_offset = all_type_parameters.Count;
1380 for (int i = 0; i < parent_offset; ++i)
1381 names[i] = all_type_parameters[i].MemberName.Name;
1384 names = new string[CurrentTypeParameters.Count];
1387 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1388 if (all_type_parameters != null)
1389 all_type_parameters.Add (MemberName.TypeParameters[i]);
1391 var name = CurrentTypeParameters[i].MemberName.Name;
1392 names[parent_offset + i] = name;
1393 for (int ii = 0; ii < parent_offset + i; ++ii) {
1394 if (names[ii] != name)
1397 var tp = CurrentTypeParameters[i];
1398 var conflict = all_type_parameters[ii];
1400 tp.WarningParentNameConflict (conflict);
1404 if (all_type_parameters == null)
1405 all_type_parameters = CurrentTypeParameters;
1411 public SourceMethodBuilder CreateMethodSymbolEntry ()
1413 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1416 var source_file = GetCompilationSourceFile ();
1417 if (source_file == null)
1420 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1424 // Creates a proxy base method call inside this container for hoisted base member calls
1426 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1428 Method proxy_method;
1431 // One proxy per base method is enough
1433 if (hoisted_base_call_proxies == null) {
1434 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1435 proxy_method = null;
1437 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1440 if (proxy_method == null) {
1441 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1443 MemberName member_name;
1444 TypeArguments targs = null;
1445 TypeSpec return_type = method.ReturnType;
1446 var local_param_types = method.Parameters.Types;
1448 if (method.IsGeneric) {
1450 // Copy all base generic method type parameters info
1452 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1453 var tparams = new TypeParameters ();
1455 targs = new TypeArguments ();
1456 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1457 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1458 var tp = hoisted_tparams[i];
1459 var tp_name = tp.Name;
1461 tp_name += "_Proxy";
1463 var local_tp = new TypeParameter (tp, null, new MemberName (tp_name, Location), null);
1464 tparams.Add (local_tp);
1466 targs.Add (new SimpleName (tp.Name, Location));
1467 targs.Arguments[i] = local_tp.Type;
1470 member_name = new MemberName (name, tparams, Location);
1473 // Mutate any method type parameters from original
1474 // to newly created hoisted version
1476 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1477 return_type = mutator.Mutate (return_type);
1478 local_param_types = mutator.Mutate (local_param_types);
1480 var inflator = new TypeParameterInflator (this, null, hoisted_tparams, targs.Arguments);
1481 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1482 var tp_spec = (TypeParameterSpec) targs.Arguments [i];
1483 tp_spec.InflateConstraints (inflator, tp_spec);
1486 member_name = new MemberName (name);
1489 var base_parameters = new Parameter[method.Parameters.Count];
1490 for (int i = 0; i < base_parameters.Length; ++i) {
1491 var base_param = method.Parameters.FixedParameters[i];
1492 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1493 base_param.Name, base_param.ModFlags, null, Location);
1494 base_parameters[i].Resolve (this, i);
1497 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, local_param_types);
1498 if (method.Parameters.HasArglist) {
1499 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1500 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1503 // Compiler generated proxy
1504 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1505 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1506 member_name, cloned_params, null);
1508 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1509 IsCompilerGenerated = true
1512 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1513 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1515 mg.SetTypeArguments (rc, targs);
1517 // Get all the method parameters and pass them as arguments
1518 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1519 Statement statement;
1520 if (method.ReturnType.Kind == MemberKind.Void)
1521 statement = new StatementExpression (real_base_call);
1523 statement = new Return (real_base_call, Location);
1525 block.AddStatement (statement);
1526 proxy_method.Block = block;
1528 members.Add (proxy_method);
1529 proxy_method.Define ();
1530 proxy_method.PrepareEmit ();
1532 hoisted_base_call_proxies.Add (method, proxy_method);
1535 return proxy_method.Spec;
1538 protected bool DefineBaseTypes ()
1540 if (IsPartialPart && Kind == MemberKind.Class)
1543 return DoDefineBaseType ();
1546 bool DoDefineBaseType ()
1548 iface_exprs = ResolveBaseTypes (out base_type_expr);
1551 if (IsPartialPart) {
1552 set_base_type = false;
1554 if (base_type_expr != null) {
1555 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1556 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1557 Report.Error (263, Location,
1558 "Partial declarations of `{0}' must not specify different base classes",
1559 GetSignatureForError ());
1561 PartialContainer.base_type_expr = base_type_expr;
1562 PartialContainer.base_type = base_type;
1563 set_base_type = true;
1567 if (iface_exprs != null) {
1568 if (PartialContainer.iface_exprs == null)
1569 PartialContainer.iface_exprs = iface_exprs;
1571 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1572 foreach (var iface_partial in iface_exprs) {
1573 if (ifaces.Contains (iface_partial))
1576 ifaces.Add (iface_partial);
1579 PartialContainer.iface_exprs = ifaces.ToArray ();
1583 PartialContainer.members.AddRange (members);
1584 if (containers != null) {
1585 if (PartialContainer.containers == null)
1586 PartialContainer.containers = new List<TypeContainer> ();
1588 PartialContainer.containers.AddRange (containers);
1591 if (PrimaryConstructorParameters != null) {
1592 if (PartialContainer.PrimaryConstructorParameters != null) {
1593 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1595 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1599 members_defined = members_defined_ok = true;
1600 caching_flags |= Flags.CloseTypeCreated;
1602 set_base_type = true;
1605 var cycle = CheckRecursiveDefinition (this);
1606 if (cycle != null) {
1607 Report.SymbolRelatedToPreviousError (cycle);
1608 if (this is Interface) {
1609 Report.Error (529, Location,
1610 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1611 GetSignatureForError (), cycle.GetSignatureForError ());
1614 PartialContainer.iface_exprs = null;
1616 Report.Error (146, Location,
1617 "Circular base class dependency involving `{0}' and `{1}'",
1618 GetSignatureForError (), cycle.GetSignatureForError ());
1621 PartialContainer.base_type = null;
1625 if (iface_exprs != null) {
1626 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1627 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1630 foreach (var iface_type in iface_exprs) {
1631 // Prevents a crash, the interface might not have been resolved: 442144
1632 if (iface_type == null)
1635 if (!spec.AddInterfaceDefined (iface_type))
1638 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1642 if (Kind == MemberKind.Interface) {
1643 spec.BaseType = Compiler.BuiltinTypes.Object;
1647 if (set_base_type) {
1652 // Base type of partial container has to be resolved before we
1653 // resolve any nested types of the container. We need to know
1654 // partial parts because the base type can be specified in file
1655 // defined after current container
1657 if (class_partial_parts != null) {
1658 foreach (var pp in class_partial_parts) {
1659 if (pp.PrimaryConstructorBaseArguments != null)
1660 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1662 pp.DoDefineBaseType ();
1672 if (base_type == null) {
1673 TypeBuilder.SetParent (null);
1677 if (spec.BaseType == base_type)
1680 spec.BaseType = base_type;
1683 spec.UpdateInflatedInstancesBaseType ();
1685 // Set base type after type creation
1686 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1689 public override void ExpandBaseInterfaces ()
1691 DoResolveTypeParameters ();
1694 DoExpandBaseInterfaces ();
1696 base.ExpandBaseInterfaces ();
1699 public void DoExpandBaseInterfaces ()
1701 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1704 caching_flags |= Flags.InterfacesExpanded;
1707 // Expand base interfaces. It cannot be done earlier because all partial
1708 // interface parts need to be defined before the type they are used from
1710 if (iface_exprs != null) {
1711 foreach (var iface in iface_exprs) {
1715 var td = iface.MemberDefinition as TypeDefinition;
1717 td.DoExpandBaseInterfaces ();
1719 if (iface.Interfaces == null)
1722 foreach (var biface in iface.Interfaces) {
1723 if (spec.AddInterfaceDefined (biface)) {
1724 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1731 // Include all base type interfaces too, see ImportTypeBase for details
1733 if (base_type != null) {
1734 var td = base_type.MemberDefinition as TypeDefinition;
1736 td.DoExpandBaseInterfaces ();
1739 // Simply use base interfaces only, they are all expanded which makes
1740 // it easy to handle generic type argument propagation with single
1743 // interface IA<T> : IB<T>
1744 // interface IB<U> : IC<U>
1747 if (base_type.Interfaces != null) {
1748 foreach (var iface in base_type.Interfaces) {
1749 spec.AddInterfaceDefined (iface);
1755 public override void PrepareEmit ()
1757 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1760 foreach (var member in members) {
1761 var pbm = member as MemberBase;
1766 base.PrepareEmit ();
1770 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1772 public override bool CreateContainer ()
1774 if (TypeBuilder != null)
1780 if (IsPartialPart) {
1781 spec = PartialContainer.spec;
1782 TypeBuilder = PartialContainer.TypeBuilder;
1783 all_tp_builders = PartialContainer.all_tp_builders;
1784 all_type_parameters = PartialContainer.all_type_parameters;
1786 if (!CreateTypeBuilder ()) {
1792 return base.CreateContainer ();
1795 protected override void DoDefineContainer ()
1801 // Replaces normal spec with predefined one when compiling corlib
1802 // and this type container defines predefined type
1804 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1806 // When compiling build-in types we start with two
1807 // version of same type. One is of BuiltinTypeSpec and
1808 // second one is ordinary TypeSpec. The unification
1809 // happens at later stage when we know which type
1810 // really matches the builtin type signature. However
1811 // that means TypeSpec create during CreateType of this
1812 // type has to be replaced with builtin one
1814 spec.SetMetaInfo (TypeBuilder);
1815 spec.MemberCache = this.spec.MemberCache;
1816 spec.DeclaringType = this.spec.DeclaringType;
1819 current_type = null;
1820 if (class_partial_parts != null) {
1821 foreach (var part in class_partial_parts) {
1823 part.current_type = null;
1828 public override void RemoveContainer (TypeContainer cont)
1830 base.RemoveContainer (cont);
1831 Members.Remove (cont);
1832 Cache.Remove (cont.MemberName.Basename);
1835 protected virtual bool DoResolveTypeParameters ()
1837 var tparams = MemberName.TypeParameters;
1838 if (tparams == null)
1841 var base_context = new BaseContext (this);
1842 for (int i = 0; i < tparams.Count; ++i) {
1843 var tp = tparams[i];
1845 if (!tp.ResolveConstraints (base_context)) {
1850 if (IsPartialPart) {
1851 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1853 tp.Create (spec, this);
1856 if (tp.OptAttributes != null) {
1857 if (pc_tp.OptAttributes == null)
1858 pc_tp.OptAttributes = tp.OptAttributes;
1860 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1865 if (IsPartialPart) {
1866 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1872 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1874 if (InTransit != null)
1879 if (base_type != null) {
1880 var ptc = base_type.MemberDefinition as TypeDefinition;
1881 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1885 if (iface_exprs != null && this is Interface) {
1886 foreach (var iface in iface_exprs) {
1887 // the interface might not have been resolved, prevents a crash, see #442144
1890 var ptc = iface.MemberDefinition as Interface;
1891 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1896 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1904 /// Populates our TypeBuilder with fields and methods
1906 public sealed override bool Define ()
1908 if (members_defined)
1909 return members_defined_ok;
1911 members_defined_ok = DoDefineMembers ();
1912 members_defined = true;
1916 return members_defined_ok;
1919 protected virtual bool DoDefineMembers ()
1921 Debug.Assert (!IsPartialPart);
1923 if (iface_exprs != null) {
1924 foreach (var iface_type in iface_exprs) {
1925 if (iface_type == null)
1928 // Ensure the base is always setup
1929 var compiled_iface = iface_type.MemberDefinition as Interface;
1930 if (compiled_iface != null)
1931 compiled_iface.Define ();
1933 iface_type.CheckObsoleteness (this, Location);
1935 if (iface_type.Arity > 0) {
1936 // TODO: passing `this' is wrong, should be base type iface instead
1937 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1939 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1940 Report.Error (1966, Location,
1941 "`{0}': cannot implement a dynamic interface `{1}'",
1942 GetSignatureForError (), iface_type.GetSignatureForError ());
1947 if (iface_type.IsGenericOrParentIsGeneric) {
1948 foreach (var prev_iface in iface_exprs) {
1949 if (prev_iface == iface_type || prev_iface == null)
1952 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1955 Report.Error (695, Location,
1956 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1957 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1962 if (Kind == MemberKind.Interface) {
1963 foreach (var iface in spec.Interfaces) {
1964 MemberCache.AddInterface (iface);
1969 if (base_type != null) {
1971 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1973 if (base_type_expr != null) {
1974 base_type.CheckObsoleteness (this, base_type_expr.Location);
1976 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1977 Report.Error (698, base_type_expr.Location,
1978 "A generic type cannot derive from `{0}' because it is an attribute class",
1979 base_type.GetSignatureForError ());
1983 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1984 if (baseContainer != null) {
1985 baseContainer.Define ();
1988 // It can trigger define of this type (for generic types only)
1990 if (HasMembersDefined)
1995 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1996 pending = PendingImplementation.GetPendingImplementations (this);
1999 var count = members.Count;
2000 for (int i = 0; i < count; ++i) {
2001 var mc = members[i] as InterfaceMemberBase;
2002 if (mc == null || !mc.IsExplicitImpl)
2007 } catch (Exception e) {
2008 throw new InternalErrorException (mc, e);
2012 for (int i = 0; i < count; ++i) {
2013 var mc = members[i] as InterfaceMemberBase;
2014 if (mc != null && mc.IsExplicitImpl)
2017 if (members[i] is TypeContainer)
2021 members[i].Define ();
2022 } catch (Exception e) {
2023 throw new InternalErrorException (members[i], e);
2028 CheckPairedOperators ();
2031 ComputeIndexerName();
2033 if (HasEquals && !HasGetHashCode) {
2034 Report.Warning (659, 3, Location,
2035 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2038 if (Kind == MemberKind.Interface && iface_exprs != null) {
2039 MemberCache.RemoveHiddenMembers (spec);
2045 void ComputeIndexerName ()
2047 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2048 if (indexers == null)
2051 string class_indexer_name = null;
2054 // Check normal indexers for consistent name, explicit interface implementation
2055 // indexers are ignored
2057 foreach (var indexer in indexers) {
2059 // FindMembers can return unfiltered full hierarchy names
2061 if (indexer.DeclaringType != spec)
2064 has_normal_indexers = true;
2066 if (class_indexer_name == null) {
2067 indexer_name = class_indexer_name = indexer.Name;
2071 if (indexer.Name != class_indexer_name)
2072 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2073 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2077 void EmitIndexerName ()
2079 if (!has_normal_indexers)
2082 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2086 var encoder = new AttributeEncoder ();
2087 encoder.Encode (GetAttributeDefaultMember ());
2088 encoder.EncodeEmptyNamedArguments ();
2090 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2093 public override void VerifyMembers ()
2096 // Check for internal or private fields that were never assigned
2098 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2099 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2100 foreach (var member in members) {
2101 if (member is Event) {
2103 // An event can be assigned from same class only, report
2104 // this warning for all accessibility modes
2106 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2107 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2112 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2113 if (is_type_exposed)
2116 member.SetIsUsed ();
2119 var f = member as Field;
2123 if (!member.IsUsed) {
2124 if (!PartialContainer.HasStructLayout) {
2125 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2126 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2128 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2129 member.GetSignatureForError ());
2136 if ((f.caching_flags & Flags.IsAssigned) != 0)
2140 // Only report 649 on level 4
2142 if (Compiler.Settings.WarningLevel < 4)
2146 // Don't be pedantic when type requires specific layout
2148 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2151 Constant c = New.Constantify (f.MemberType, f.Location);
2154 value = c.GetValueAsLiteral ();
2155 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2162 value = " `" + value + "'";
2164 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2165 f.GetSignatureForError (), value);
2169 base.VerifyMembers ();
2172 public override void Emit ()
2174 if (Interfaces != null) {
2175 foreach (var iface in Interfaces) {
2176 if (iface.HasNamedTupleElement) {
2177 throw new NotImplementedException ("named tuples for .interfaceimpl");
2182 if (OptAttributes != null)
2183 OptAttributes.Emit ();
2185 if (!IsCompilerGenerated) {
2187 MemberSpec candidate;
2188 bool overrides = false;
2189 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2190 if (conflict_symbol == null && candidate == null) {
2191 if ((ModFlags & Modifiers.NEW) != 0)
2192 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2193 GetSignatureForError ());
2195 if ((ModFlags & Modifiers.NEW) == 0) {
2196 if (candidate == null)
2197 candidate = conflict_symbol;
2199 Report.SymbolRelatedToPreviousError (candidate);
2200 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2201 GetSignatureForError (), candidate.GetSignatureForError ());
2206 // Run constraints check on all possible generic types
2207 if (base_type != null && base_type_expr != null) {
2208 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2211 if (iface_exprs != null) {
2212 foreach (var iface_type in iface_exprs) {
2213 if (iface_type == null)
2216 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2221 if (all_tp_builders != null) {
2222 int current_starts_index = CurrentTypeParametersStartIndex;
2223 for (int i = 0; i < all_tp_builders.Length; i++) {
2224 if (i < current_starts_index) {
2225 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2227 var tp = CurrentTypeParameters [i - current_starts_index];
2228 tp.CheckGenericConstraints (!IsObsolete);
2234 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2235 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2238 if (Kind == MemberKind.Struct && !HasStructLayout && HasInstanceField) {
2239 TypeBuilder.__SetLayout (0, 0);
2242 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2243 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2248 for (int i = 0; i < members.Count; i++) {
2250 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2257 CheckAttributeClsCompliance ();
2259 if (pending != null)
2260 pending.VerifyPendingMethods ();
2264 void CheckAttributeClsCompliance ()
2266 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2269 foreach (var m in members) {
2270 var c = m as Constructor;
2274 if (c.HasCompliantArgs)
2278 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2281 public sealed override void EmitContainer ()
2283 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2289 public override void CloseContainer ()
2291 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2294 // Close base type container first to avoid TypeLoadException
2295 if (spec.BaseType != null) {
2296 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2297 if (btype != null) {
2298 btype.CloseContainer ();
2300 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2306 caching_flags |= Flags.CloseTypeCreated;
2307 TypeBuilder.CreateType ();
2308 } catch (TypeLoadException) {
2310 // This is fine, the code still created the type
2312 } catch (Exception e) {
2313 throw new InternalErrorException (this, e);
2316 base.CloseContainer ();
2319 initialized_fields = null;
2320 initialized_static_fields = null;
2322 OptAttributes = null;
2326 // Performs the validation on a Method's modifiers (properties have
2327 // the same properties).
2329 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2331 public bool MethodModifiersValid (MemberCore mc)
2333 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2334 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2336 var flags = mc.ModFlags;
2339 // At most one of static, virtual or override
2341 if ((flags & Modifiers.STATIC) != 0){
2342 if ((flags & vao) != 0){
2343 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2344 mc.GetSignatureForError ());
2349 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2350 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2351 mc.GetSignatureForError ());
2356 // If the declaration includes the abstract modifier, then the
2357 // declaration does not include static, virtual or extern
2359 if ((flags & Modifiers.ABSTRACT) != 0){
2360 if ((flags & Modifiers.EXTERN) != 0){
2362 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2366 if ((flags & Modifiers.SEALED) != 0) {
2367 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2371 if ((flags & Modifiers.VIRTUAL) != 0){
2372 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2376 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2377 Report.SymbolRelatedToPreviousError (this);
2378 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2379 mc.GetSignatureForError (), GetSignatureForError ());
2384 if ((flags & Modifiers.PRIVATE) != 0){
2385 if ((flags & vao) != 0){
2386 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2391 if ((flags & Modifiers.SEALED) != 0){
2392 if ((flags & Modifiers.OVERRIDE) == 0){
2393 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2401 protected override bool VerifyClsCompliance ()
2403 if (!base.VerifyClsCompliance ())
2406 // Check all container names for user classes
2407 if (Kind != MemberKind.Delegate)
2408 MemberCache.VerifyClsCompliance (Definition, Report);
2410 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2411 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2412 GetSignatureForError (), BaseType.GetSignatureForError ());
2418 /// Performs checks for an explicit interface implementation. First it
2419 /// checks whether the `interface_type' is a base inteface implementation.
2420 /// Then it checks whether `name' exists in the interface type.
2422 public bool VerifyImplements (InterfaceMemberBase mb)
2424 var ifaces = PartialContainer.Interfaces;
2425 if (ifaces != null) {
2426 foreach (TypeSpec t in ifaces){
2427 if (t == mb.InterfaceType || t == null)
2430 var expanded_base = t.Interfaces;
2431 if (expanded_base == null)
2434 foreach (var bt in expanded_base) {
2435 if (bt == mb.InterfaceType)
2441 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2442 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2443 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2448 // Used for visiblity checks to tests whether this definition shares
2449 // base type baseType, it does member-definition search
2451 public bool IsBaseTypeDefinition (TypeSpec baseType)
2453 // RootContext check
2454 if (TypeBuilder == null)
2459 if (type.MemberDefinition == baseType.MemberDefinition)
2462 type = type.BaseType;
2463 } while (type != null);
2468 public override bool IsClsComplianceRequired ()
2471 return PartialContainer.IsClsComplianceRequired ();
2473 return base.IsClsComplianceRequired ();
2476 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2478 return Module.DeclaringAssembly == assembly;
2481 public virtual bool IsUnmanagedType ()
2486 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2488 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2492 // Public function used to locate types.
2494 // Returns: Type or null if they type can not be found.
2496 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2498 FullNamedExpression e;
2499 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2505 var tp = CurrentTypeParameters;
2507 TypeParameter tparam = tp.Find (name);
2509 e = new TypeParameterExpr (tparam, Location.Null);
2514 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2516 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2517 e = new TypeExpression (t, Location.Null);
2519 var errors = Compiler.Report.Errors;
2520 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2522 // TODO: LookupNamespaceOrType does more than just lookup. The result
2523 // cannot be cached or the error reporting won't happen
2524 if (errors != Compiler.Report.Errors)
2529 // TODO MemberCache: How to cache arity stuff ?
2530 if (arity == 0 && mode == LookupMode.Normal)
2536 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2538 // Has any nested type
2539 // Does not work, because base type can have
2540 //if (PartialContainer.Types == null)
2543 var container = PartialContainer.CurrentType;
2544 return MemberCache.FindNestedType (container, name, arity, false);
2547 public void Mark_HasEquals ()
2549 cached_method |= CachedMethods.Equals;
2552 public void Mark_HasGetHashCode ()
2554 cached_method |= CachedMethods.GetHashCode;
2557 public override void WriteDebugSymbol (MonoSymbolFile file)
2562 foreach (var m in members) {
2563 m.WriteDebugSymbol (file);
2568 /// Method container contains Equals method
2570 public bool HasEquals {
2572 return (cached_method & CachedMethods.Equals) != 0;
2577 /// Method container contains GetHashCode method
2579 public bool HasGetHashCode {
2581 return (cached_method & CachedMethods.GetHashCode) != 0;
2585 public bool HasStaticFieldInitializer {
2587 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2591 cached_method |= CachedMethods.HasStaticFieldInitializer;
2593 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2597 public override string DocCommentHeader {
2598 get { return "T:"; }
2602 public abstract class ClassOrStruct : TypeDefinition
2604 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2606 SecurityType declarative_security;
2607 protected Constructor generated_primary_constructor;
2609 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2610 : base (parent, name, attrs, kind)
2614 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2616 protected override TypeAttributes TypeAttr {
2618 TypeAttributes ta = base.TypeAttr;
2619 if (!has_static_constructor)
2620 ta |= TypeAttributes.BeforeFieldInit;
2622 if (Kind == MemberKind.Class) {
2623 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2625 ta |= StaticClassAttribute;
2627 ta |= TypeAttributes.SequentialLayout;
2634 public override void AddNameToContainer (MemberCore symbol, string name)
2636 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2637 if (symbol is TypeParameter) {
2638 Report.Error (694, symbol.Location,
2639 "Type parameter `{0}' has same name as containing type, or method",
2640 symbol.GetSignatureForError ());
2644 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2645 if (imb == null || !imb.IsExplicitImpl) {
2646 Report.SymbolRelatedToPreviousError (this);
2647 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2648 symbol.GetSignatureForError ());
2653 base.AddNameToContainer (symbol, name);
2656 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2658 if (a.IsValidSecurityAttribute ()) {
2659 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2663 if (a.Type == pa.StructLayout) {
2664 PartialContainer.HasStructLayout = true;
2665 if (a.IsExplicitLayoutKind ())
2666 PartialContainer.HasExplicitLayout = true;
2669 if (a.Type == pa.Dynamic) {
2670 a.Error_MisusedDynamicAttribute ();
2674 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2678 /// Defines the default constructors
2680 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2682 // The default instance constructor is public
2683 // If the class is abstract, the default constructor is protected
2684 // The default static constructor is private
2687 ParametersCompiled parameters = null;
2689 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2690 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2692 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2693 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2696 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2697 if (Kind == MemberKind.Class)
2698 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2700 if (PrimaryConstructorParameters != null && !is_static) {
2701 c.IsPrimaryConstructor = true;
2702 c.caching_flags |= Flags.MethodOverloadsExist;
2705 AddConstructor (c, true);
2706 if (PrimaryConstructorBlock == null) {
2707 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2708 IsCompilerGenerated = true
2711 c.Block = PrimaryConstructorBlock;
2717 protected override bool DoDefineMembers ()
2719 CheckProtectedModifier ();
2721 if (PrimaryConstructorParameters != null) {
2723 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2724 if (p.Name == MemberName.Name) {
2725 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2726 GetSignatureForError ());
2729 if (CurrentTypeParameters != null) {
2730 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2731 var tp = CurrentTypeParameters [i];
2732 if (p.Name == tp.Name) {
2733 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2734 GetSignatureForError (), p.GetSignatureForError ());
2741 base.DoDefineMembers ();
2746 public override void PrepareEmit ()
2748 var s = this as Struct;
2749 if (s == null || !s.HasUnmanagedCheckDone) {
2750 for (int i = 0; i < Members.Count; ++i) {
2751 var f = Members [i] as Field;
2752 if (f == null || f.MemberType == null || !f.MemberType.IsPointer)
2755 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2759 base.PrepareEmit ();
2762 public override void Emit ()
2764 if (!has_static_constructor && HasStaticFieldInitializer) {
2765 var c = DefineDefaultConstructor (true);
2771 if (declarative_security != null) {
2772 foreach (var de in declarative_security) {
2774 TypeBuilder.__AddDeclarativeSecurity (de);
2776 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2784 public sealed class Class : ClassOrStruct
2786 const Modifiers AllowedModifiers =
2789 Modifiers.PROTECTED |
2790 Modifiers.INTERNAL |
2792 Modifiers.ABSTRACT |
2797 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2798 : base (parent, name, attrs, MemberKind.Class)
2800 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2801 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2802 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2805 public override void Accept (StructuralVisitor visitor)
2807 visitor.Visit (this);
2810 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2812 var pmn = MemberName;
2813 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2814 Report.Error (537, Location,
2815 "The class System.Object cannot have a base class or implement an interface.");
2817 base.SetBaseTypes (baseTypes);
2820 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2822 if (a.Type == pa.AttributeUsage) {
2823 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2824 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2828 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2829 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2833 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2834 a.Error_MissingGuidAttribute ();
2838 if (a.Type == pa.Extension) {
2839 a.Error_MisusedExtensionAttribute ();
2843 if (a.Type.IsConditionallyExcluded (this))
2846 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2849 public override AttributeTargets AttributeTargets {
2851 return AttributeTargets.Class;
2855 protected override bool DoDefineMembers ()
2857 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2858 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2861 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2862 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2866 if (PrimaryConstructorParameters != null) {
2867 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2868 PrimaryConstructorParameters = null;
2871 foreach (var m in Members) {
2872 if (m is Operator) {
2873 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2877 if (m is Destructor) {
2878 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2883 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2887 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2890 if (m is Constructor) {
2891 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2895 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2898 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2899 generated_primary_constructor = DefineDefaultConstructor (false);
2902 return base.DoDefineMembers ();
2905 public override void Emit ()
2909 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2910 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2912 if (base_type != null) {
2913 if (base_type.HasDynamicElement)
2914 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2915 if (base_type.HasNamedTupleElement)
2916 Module.PredefinedAttributes.TupleElementNames.EmitAttribute (TypeBuilder, base_type, Location);
2920 public override void GetCompletionStartingWith (string prefix, List<string> results)
2922 base.GetCompletionStartingWith (prefix, results);
2925 while (bt != null) {
2926 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2931 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2933 var ifaces = base.ResolveBaseTypes (out base_class);
2935 if (base_class == null) {
2936 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2937 base_type = Compiler.BuiltinTypes.Object;
2939 if (base_type.IsGenericParameter){
2940 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2941 GetSignatureForError (), base_type.GetSignatureForError ());
2942 } else if (base_type.IsStatic) {
2943 Report.SymbolRelatedToPreviousError (base_type);
2944 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2945 GetSignatureForError (), base_type.GetSignatureForError ());
2946 } else if (base_type.IsSealed) {
2947 Report.SymbolRelatedToPreviousError (base_type);
2948 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2949 GetSignatureForError (), base_type.GetSignatureForError ());
2950 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2951 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2952 GetSignatureForError (), base_type.GetSignatureForError ());
2955 switch (base_type.BuiltinType) {
2956 case BuiltinTypeSpec.Type.Enum:
2957 case BuiltinTypeSpec.Type.ValueType:
2958 case BuiltinTypeSpec.Type.MulticastDelegate:
2959 case BuiltinTypeSpec.Type.Delegate:
2960 case BuiltinTypeSpec.Type.Array:
2961 if (!(spec is BuiltinTypeSpec)) {
2962 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2963 GetSignatureForError (), base_type.GetSignatureForError ());
2965 base_type = Compiler.BuiltinTypes.Object;
2970 if (!IsAccessibleAs (base_type)) {
2971 Report.SymbolRelatedToPreviousError (base_type);
2972 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2973 base_type.GetSignatureForError (), GetSignatureForError ());
2977 if (PartialContainer.IsStatic && ifaces != null) {
2978 foreach (var t in ifaces)
2979 Report.SymbolRelatedToPreviousError (t);
2980 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2986 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2987 /// Valid only for attribute classes.
2988 public override string[] ConditionalConditions ()
2990 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2993 caching_flags &= ~Flags.Excluded_Undetected;
2995 if (OptAttributes == null)
2998 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
3002 string[] conditions = new string[attrs.Length];
3003 for (int i = 0; i < conditions.Length; ++i)
3004 conditions[i] = attrs[i].GetConditionalAttributeValue ();
3006 caching_flags |= Flags.Excluded;
3011 public sealed class Struct : ClassOrStruct
3013 bool is_unmanaged, has_unmanaged_check_done, requires_delayed_unmanagedtype_check;
3017 // Modifiers allowed in a struct declaration
3019 const Modifiers AllowedModifiers =
3022 Modifiers.PROTECTED |
3023 Modifiers.INTERNAL |
3027 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3028 : base (parent, name, attrs, MemberKind.Struct)
3030 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3031 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
3032 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3035 public override AttributeTargets AttributeTargets {
3037 return AttributeTargets.Struct;
3041 public override void Accept (StructuralVisitor visitor)
3043 visitor.Visit (this);
3046 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3048 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3051 // When struct constains fixed fixed and struct layout has explicitly
3052 // set CharSet, its value has to be propagated to compiler generated
3055 if (a.Type == pa.StructLayout) {
3056 var value = a.GetNamedValue ("CharSet");
3060 for (int i = 0; i < Members.Count; ++i) {
3061 FixedField ff = Members [i] as FixedField;
3065 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3070 bool CheckStructCycles ()
3076 foreach (var member in Members) {
3077 var field = member as Field;
3081 TypeSpec ftype = field.Spec.MemberType;
3082 if (!ftype.IsStruct)
3085 if (ftype is BuiltinTypeSpec)
3088 foreach (var targ in ftype.TypeArguments) {
3089 if (!CheckFieldTypeCycle (targ)) {
3090 Report.Error (523, field.Location,
3091 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3092 field.GetSignatureForError (), ftype.GetSignatureForError ());
3098 // Static fields of exactly same type are allowed
3100 if (field.IsStatic && ftype == CurrentType)
3103 if (!CheckFieldTypeCycle (ftype)) {
3104 Report.Error (523, field.Location,
3105 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3106 field.GetSignatureForError (), ftype.GetSignatureForError ());
3115 static bool CheckFieldTypeCycle (TypeSpec ts)
3117 var fts = ts.MemberDefinition as Struct;
3121 return fts.CheckStructCycles ();
3124 protected override bool DoDefineMembers ()
3126 var res = base.DoDefineMembers ();
3128 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3129 generated_primary_constructor = DefineDefaultConstructor (false);
3130 generated_primary_constructor.Define ();
3136 public override void Emit ()
3138 CheckStructCycles ();
3143 public bool HasUnmanagedCheckDone {
3145 return has_unmanaged_check_done;
3149 bool HasUserDefaultConstructor ()
3151 foreach (var m in PartialContainer.Members) {
3152 var c = m as Constructor;
3156 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3163 public override bool IsUnmanagedType ()
3165 if (has_unmanaged_check_done)
3166 return is_unmanaged;
3168 if (requires_delayed_unmanagedtype_check)
3171 var parent_def = Parent.PartialContainer;
3172 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3173 has_unmanaged_check_done = true;
3177 if (HasInstanceField) {
3178 requires_delayed_unmanagedtype_check = true;
3180 foreach (var member in Members) {
3181 var f = member as Field;
3188 // It can happen when recursive unmanaged types are defined
3189 // struct S { S* s; }
3190 TypeSpec mt = f.MemberType;
3198 has_unmanaged_check_done = true;
3202 has_unmanaged_check_done = true;
3205 is_unmanaged = true;
3209 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3211 var ifaces = base.ResolveBaseTypes (out base_class);
3212 base_type = Compiler.BuiltinTypes.ValueType;
3220 public sealed class Interface : TypeDefinition {
3223 /// Modifiers allowed in a class declaration
3225 const Modifiers AllowedModifiers =
3228 Modifiers.PROTECTED |
3229 Modifiers.INTERNAL |
3233 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3234 : base (parent, name, attrs, MemberKind.Interface)
3236 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3238 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3239 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3244 public override AttributeTargets AttributeTargets {
3246 return AttributeTargets.Interface;
3250 protected override TypeAttributes TypeAttr {
3252 const TypeAttributes DefaultTypeAttributes =
3253 TypeAttributes.AutoLayout |
3254 TypeAttributes.Abstract |
3255 TypeAttributes.Interface;
3257 return base.TypeAttr | DefaultTypeAttributes;
3263 public override void Accept (StructuralVisitor visitor)
3265 visitor.Visit (this);
3268 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3270 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3271 a.Error_MissingGuidAttribute ();
3275 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3278 protected override bool VerifyClsCompliance ()
3280 if (!base.VerifyClsCompliance ())
3283 if (iface_exprs != null) {
3284 foreach (var iface in iface_exprs) {
3285 if (iface.IsCLSCompliant ())
3288 Report.SymbolRelatedToPreviousError (iface);
3289 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3290 GetSignatureForError (), iface.GetSignatureForError ());
3298 public abstract class InterfaceMemberBase : MemberBase
3301 // Common modifiers allowed in a class declaration
3303 protected const Modifiers AllowedModifiersClass =
3306 Modifiers.PROTECTED |
3307 Modifiers.INTERNAL |
3312 Modifiers.OVERRIDE |
3313 Modifiers.ABSTRACT |
3318 // Common modifiers allowed in a struct declaration
3320 protected const Modifiers AllowedModifiersStruct =
3323 Modifiers.PROTECTED |
3324 Modifiers.INTERNAL |
3327 Modifiers.OVERRIDE |
3332 // Common modifiers allowed in a interface declaration
3334 protected const Modifiers AllowedModifiersInterface =
3339 // Whether this is an interface member.
3341 public bool IsInterface;
3344 // If true, this is an explicit interface implementation
3346 public readonly bool IsExplicitImpl;
3348 protected bool is_external_implementation;
3351 // The interface type we are explicitly implementing
3353 public TypeSpec InterfaceType;
3356 // The method we're overriding if this is an override method.
3358 protected MethodSpec base_method;
3360 readonly Modifiers explicit_mod_flags;
3361 public MethodAttributes flags;
3363 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3364 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3366 IsInterface = parent.Kind == MemberKind.Interface;
3367 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3368 explicit_mod_flags = mod;
3371 public abstract Variance ExpectedMemberTypeVariance { get; }
3373 protected override bool CheckBase ()
3375 if (!base.CheckBase ())
3378 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3379 CheckForDuplications ();
3384 // For System.Object only
3385 if (Parent.BaseType == null)
3388 MemberSpec candidate;
3389 bool overrides = false;
3390 var base_member = FindBaseMember (out candidate, ref overrides);
3392 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3393 if (base_member == null) {
3394 if (candidate == null) {
3395 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3396 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3397 "object.Finalize()");
3399 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3400 GetSignatureForError (), SimpleName.GetMemberType (this));
3403 Report.SymbolRelatedToPreviousError (candidate);
3405 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3406 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3407 else if (this is PropertyBase)
3408 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3409 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3411 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3412 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3419 // Handles ambiguous overrides
3421 if (candidate != null) {
3422 Report.SymbolRelatedToPreviousError (candidate);
3423 Report.SymbolRelatedToPreviousError (base_member);
3425 // Get member definition for error reporting
3426 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3427 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3429 Report.Error (462, Location,
3430 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3431 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3434 if (!CheckOverrideAgainstBase (base_member))
3437 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3439 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3440 Report.SymbolRelatedToPreviousError (base_member);
3441 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3442 GetSignatureForError (), base_member.GetSignatureForError ());
3445 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3446 Report.SymbolRelatedToPreviousError (base_member);
3447 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3448 GetSignatureForError (), base_member.GetSignatureForError ());
3452 base_method = base_member as MethodSpec;
3456 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3457 base_member = candidate;
3459 if (base_member == null) {
3460 if ((ModFlags & Modifiers.NEW) != 0) {
3461 if (base_member == null) {
3462 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3463 GetSignatureForError ());
3467 if ((ModFlags & Modifiers.NEW) == 0) {
3468 ModFlags |= Modifiers.NEW;
3469 if (!IsCompilerGenerated) {
3470 Report.SymbolRelatedToPreviousError (base_member);
3471 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3472 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",
3473 GetSignatureForError (), base_member.GetSignatureForError ());
3475 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3476 GetSignatureForError (), base_member.GetSignatureForError ());
3481 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3482 switch (base_member.Kind) {
3483 case MemberKind.Event:
3484 case MemberKind.Indexer:
3485 case MemberKind.Method:
3486 case MemberKind.Property:
3487 Report.SymbolRelatedToPreviousError (base_member);
3488 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3489 GetSignatureForError (), base_member.GetSignatureForError ());
3498 protected virtual bool CheckForDuplications ()
3500 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3504 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3505 // that have been defined.
3507 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3511 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3512 Report.SymbolRelatedToPreviousError (base_member);
3513 Report.Error (506, Location,
3514 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3515 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3519 // Now we check that the overriden method is not final
3520 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3521 Report.SymbolRelatedToPreviousError (base_member);
3522 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3523 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3527 var base_member_type = ((IInterfaceMemberSpec)base_member).MemberType;
3528 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3529 Report.SymbolRelatedToPreviousError (base_member);
3530 if (((base_member_type.Kind ^ MemberType.Kind) & MemberKind.ByRef) != 0) {
3531 Report.Error (8148, Location, "`{0}': must {2}return by reference to match overridden member `{1}'",
3532 GetSignatureForError (), base_member.GetSignatureForError (), base_member_type.Kind == MemberKind.ByRef ? "" : "not ");
3533 } else if (this is PropertyBasedMember) {
3534 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3535 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3537 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3538 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3541 } else if (!NamedTupleSpec.CheckOverrideName (MemberType, base_member_type)) {
3542 // CSC: Should be different error code
3543 Report.Error (8139, Location, "`{0}': cannot change return type tuple element names when overriding inherited member `{1}'",
3544 GetSignatureForError (), base_member.GetSignatureForError ());
3548 var base_params = base_member as IParametersMember;
3549 if (base_params != null) {
3550 if (!NamedTupleSpec.CheckOverrideName ((IParametersMember)this, base_params)) {
3551 Report.Error (8139, Location, "`{0}': cannot change tuple element names when overriding inherited member `{1}'",
3552 GetSignatureForError (), base_member.GetSignatureForError ());
3560 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3562 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3563 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3565 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3567 // It must be at least "protected"
3569 if ((thisp & Modifiers.PROTECTED) == 0) {
3574 // when overriding protected internal, the method can be declared
3575 // protected internal only within the same assembly or assembly
3576 // which has InternalsVisibleTo
3578 if ((thisp & Modifiers.INTERNAL) != 0) {
3579 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3583 // protected overriding protected internal inside same assembly
3584 // requires internal modifier as well
3586 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3593 return thisp == base_classp;
3596 public override bool Define ()
3599 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3600 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3602 flags = MethodAttributes.Public |
3603 MethodAttributes.Abstract |
3604 MethodAttributes.HideBySig |
3605 MethodAttributes.NewSlot |
3606 MethodAttributes.Virtual;
3608 Parent.PartialContainer.MethodModifiersValid (this);
3610 flags = ModifiersExtensions.MethodAttr (ModFlags);
3613 if (IsExplicitImpl) {
3614 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3615 if (InterfaceType == null)
3618 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3619 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3620 GetSignatureForError ());
3623 if (!InterfaceType.IsInterface) {
3624 Report.SymbolRelatedToPreviousError (InterfaceType);
3625 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3626 InterfaceType.GetSignatureForError ());
3628 Parent.PartialContainer.VerifyImplements (this);
3631 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3633 allowed_explicit |= Modifiers.ASYNC;
3635 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3638 return base.Define ();
3641 protected bool DefineParameters (ParametersCompiled parameters)
3643 if (!parameters.Resolve (this))
3647 for (int i = 0; i < parameters.Count; ++i) {
3648 Parameter p = parameters [i];
3650 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3651 p.Warning_UselessOptionalParameter (Report);
3653 if (p.CheckAccessibility (this))
3656 TypeSpec t = parameters.Types [i];
3657 Report.SymbolRelatedToPreviousError (t);
3658 if (this is Indexer)
3659 Report.Error (55, Location,
3660 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3661 t.GetSignatureForError (), GetSignatureForError ());
3662 else if (this is Operator)
3663 Report.Error (57, Location,
3664 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3665 t.GetSignatureForError (), GetSignatureForError ());
3667 Report.Error (51, Location,
3668 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3669 t.GetSignatureForError (), GetSignatureForError ());
3675 protected override void DoMemberTypeDependentChecks ()
3677 base.DoMemberTypeDependentChecks ();
3679 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3682 public override void Emit()
3684 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3685 // We are more strict than csc and report this as an error because SRE does not allow emit that
3686 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3687 if (this is Constructor) {
3688 Report.Warning (824, 1, Location,
3689 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3691 Report.Warning (626, 1, Location,
3692 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3693 GetSignatureForError ());
3700 public override bool EnableOverloadChecks (MemberCore overload)
3703 // Two members can differ in their explicit interface
3704 // type parameter only
3706 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3707 if (imb != null && imb.IsExplicitImpl) {
3708 if (IsExplicitImpl) {
3709 caching_flags |= Flags.MethodOverloadsExist;
3714 return IsExplicitImpl;
3717 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3719 var base_modifiers = base_member.Modifiers;
3721 // Remove internal modifier from types which are not internally accessible
3722 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3723 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3724 base_modifiers = Modifiers.PROTECTED;
3726 Report.SymbolRelatedToPreviousError (base_member);
3727 Report.Error (507, member.Location,
3728 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3729 member.GetSignatureForError (),
3730 ModifiersExtensions.AccessibilityName (base_modifiers),
3731 base_member.GetSignatureForError ());
3734 protected void Error_StaticReturnType ()
3736 Report.Error (722, Location,
3737 "`{0}': static types cannot be used as return types",
3738 MemberType.GetSignatureForError ());
3742 /// Gets base method and its return type
3744 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3746 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3750 // The "short" name of this property / indexer / event. This is the
3751 // name without the explicit interface.
3753 public string ShortName {
3754 get { return MemberName.Name; }
3758 // Returns full metadata method name
3760 public string GetFullName (MemberName name)
3762 return GetFullName (name.Name);
3765 public string GetFullName (string name)
3767 if (!IsExplicitImpl)
3771 // When dealing with explicit members a full interface type
3772 // name is added to member name to avoid possible name conflicts
3774 // We use CSharpName which gets us full name with benefit of
3775 // replacing predefined names which saves some space and name
3778 return InterfaceType.GetSignatureForError () + "." + name;
3781 public override string GetSignatureForDocumentation ()
3784 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3786 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3789 public override bool IsUsed
3791 get { return IsExplicitImpl || base.IsUsed; }
3794 public override void SetConstraints (List<Constraints> constraints_list)
3796 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3797 Report.Error (460, Location,
3798 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3799 GetSignatureForError ());
3802 base.SetConstraints (constraints_list);
3806 public abstract class MemberBase : MemberCore
3808 protected FullNamedExpression type_expr;
3809 protected TypeSpec member_type;
3810 public new TypeDefinition Parent;
3812 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3813 : base (parent, name, attrs)
3815 this.Parent = parent;
3816 this.type_expr = type;
3818 if (name != MemberName.Null)
3819 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3824 public TypeSpec MemberType {
3830 public FullNamedExpression TypeExpression {
3842 // Main member define entry
3844 public override bool Define ()
3846 DoMemberTypeIndependentChecks ();
3849 // Returns false only when type resolution failed
3851 if (!ResolveMemberType ())
3854 DoMemberTypeDependentChecks ();
3859 // Any type_name independent checks
3861 protected virtual void DoMemberTypeIndependentChecks ()
3863 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3864 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3865 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3866 GetSignatureForError (), Parent.GetSignatureForError ());
3871 // Any type_name dependent checks
3873 protected virtual void DoMemberTypeDependentChecks ()
3875 // verify accessibility
3876 if (!IsAccessibleAs (MemberType)) {
3877 Report.SymbolRelatedToPreviousError (MemberType);
3878 if (this is Property)
3879 Report.Error (53, Location,
3880 "Inconsistent accessibility: property type `" +
3881 MemberType.GetSignatureForError () + "' is less " +
3882 "accessible than property `" + GetSignatureForError () + "'");
3883 else if (this is Indexer)
3884 Report.Error (54, Location,
3885 "Inconsistent accessibility: indexer return type `" +
3886 MemberType.GetSignatureForError () + "' is less " +
3887 "accessible than indexer `" + GetSignatureForError () + "'");
3888 else if (this is MethodCore) {
3889 if (this is Operator)
3890 Report.Error (56, Location,
3891 "Inconsistent accessibility: return type `" +
3892 MemberType.GetSignatureForError () + "' is less " +
3893 "accessible than operator `" + GetSignatureForError () + "'");
3895 Report.Error (50, Location,
3896 "Inconsistent accessibility: return type `" +
3897 MemberType.GetSignatureForError () + "' is less " +
3898 "accessible than method `" + GetSignatureForError () + "'");
3899 } else if (this is Event) {
3900 Report.Error (7025, Location,
3901 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3902 MemberType.GetSignatureForError (), GetSignatureForError ());
3904 Report.Error (52, Location,
3905 "Inconsistent accessibility: field type `" +
3906 MemberType.GetSignatureForError () + "' is less " +
3907 "accessible than field `" + GetSignatureForError () + "'");
3912 protected void IsTypePermitted ()
3914 if (MemberType.IsSpecialRuntimeType) {
3915 if (Parent is StateMachine) {
3916 Report.Error (4012, Location,
3917 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3918 MemberType.GetSignatureForError ());
3919 } else if (Parent is HoistedStoreyClass) {
3920 Report.Error (4013, Location,
3921 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3922 MemberType.GetSignatureForError ());
3924 Report.Error (610, Location,
3925 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3930 protected virtual bool CheckBase ()
3932 CheckProtectedModifier ();
3937 public override string GetSignatureForDocumentation ()
3939 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3942 public virtual void PrepareEmit ()
3944 if (member_type != null && type_expr != null)
3945 member_type.CheckObsoleteness (this, type_expr.Location);
3948 protected virtual bool ResolveMemberType ()
3950 if (member_type != null)
3951 throw new InternalErrorException ("Multi-resolve");
3953 member_type = type_expr.ResolveAsType (this);
3954 return member_type != null;