2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2011 Novell, Inc
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Security;
20 using System.Security.Permissions;
22 using System.Diagnostics;
23 using Mono.CompilerServices.SymbolWriter;
26 using XmlElement = System.Object;
30 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
31 using IKVM.Reflection;
32 using IKVM.Reflection.Emit;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
42 // General types container, used as a base class for all constructs which can hold types
44 public abstract class TypeContainer : MemberCore
46 public readonly MemberKind Kind;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public int CounterAnonymousMethods { get; set; }
57 public int CounterAnonymousContainers { get; set; }
58 public int CounterSwitchTypes { get; set; }
60 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
61 : base (parent, name, attrs)
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. User
98 public Attributes UnattachedAttributes {
102 public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
104 AddTypeContainerMember (c);
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 existing.AddPartialPart (next_part);
193 AddTypeContainerMember (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
198 AddTypeContainerMember (tc);
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 protected virtual void AddTypeContainerMember (TypeContainer tc)
218 public virtual void CloseContainer ()
220 if (containers != null) {
221 foreach (TypeContainer tc in containers) {
222 tc.CloseContainer ();
227 public virtual void CreateMetadataName (StringBuilder sb)
229 if (Parent != null && Parent.MemberName != null)
230 Parent.CreateMetadataName (sb);
232 MemberName.CreateMetadataName (sb);
235 public virtual bool CreateContainer ()
237 if (containers != null) {
238 foreach (TypeContainer tc in containers) {
239 tc.CreateContainer ();
246 public override bool Define ()
248 if (containers != null) {
249 foreach (TypeContainer tc in containers) {
254 // Release cache used by parser only
255 if (Module.Evaluator == null) {
256 defined_names = null;
258 defined_names.Clear ();
264 public virtual void PrepareEmit ()
266 if (containers != null) {
267 foreach (var t in containers) {
270 } catch (Exception e) {
271 if (MemberName == MemberName.Null)
274 throw new InternalErrorException (t, e);
280 public virtual bool DefineContainer ()
287 DoDefineContainer ();
289 if (containers != null) {
290 foreach (TypeContainer tc in containers) {
292 tc.DefineContainer ();
293 } catch (Exception e) {
294 if (MemberName == MemberName.Null)
297 throw new InternalErrorException (tc, e);
305 public virtual void ExpandBaseInterfaces ()
307 if (containers != null) {
308 foreach (TypeContainer tc in containers) {
309 tc.ExpandBaseInterfaces ();
314 protected virtual void DefineNamespace ()
316 if (containers != null) {
317 foreach (var tc in containers) {
319 tc.DefineNamespace ();
320 } catch (Exception e) {
321 throw new InternalErrorException (tc, e);
327 protected virtual void DoDefineContainer ()
331 public virtual void EmitContainer ()
333 if (containers != null) {
334 for (int i = 0; i < containers.Count; ++i)
335 containers[i].EmitContainer ();
339 protected void Error_MissingPartialModifier (MemberCore type)
341 Report.Error (260, type.Location,
342 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
343 type.GetSignatureForError ());
346 public override string GetSignatureForDocumentation ()
348 if (Parent != null && Parent.MemberName != null)
349 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
351 return MemberName.GetSignatureForDocumentation ();
354 public override string GetSignatureForError ()
356 if (Parent != null && Parent.MemberName != null)
357 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
359 return MemberName.GetSignatureForError ();
362 public virtual string GetSignatureForMetadata ()
364 var sb = new StringBuilder ();
365 CreateMetadataName (sb);
366 return sb.ToString ();
369 public virtual void RemoveContainer (TypeContainer cont)
371 if (containers != null)
372 containers.Remove (cont);
374 var tc = Parent == Module ? Module : this;
375 tc.defined_names.Remove (cont.MemberName.Basename);
378 public virtual void VerifyMembers ()
380 if (containers != null) {
381 foreach (TypeContainer tc in containers)
386 public override void WriteDebugSymbol (MonoSymbolFile file)
388 if (containers != null) {
389 foreach (TypeContainer tc in containers) {
390 tc.WriteDebugSymbol (file);
396 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
399 // Different context is needed when resolving type container base
400 // types. Type names come from the parent scope but type parameter
401 // names from the container scope.
403 public struct BaseContext : IMemberContext
407 public BaseContext (TypeContainer tc)
412 #region IMemberContext Members
414 public CompilerContext Compiler {
415 get { return tc.Compiler; }
418 public TypeSpec CurrentType {
419 get { return tc.PartialContainer.CurrentType; }
422 public TypeParameters CurrentTypeParameters {
423 get { return tc.PartialContainer.CurrentTypeParameters; }
426 public MemberCore CurrentMemberDefinition {
430 public bool IsObsolete {
431 get { return tc.IsObsolete; }
434 public bool IsUnsafe {
435 get { return tc.IsUnsafe; }
438 public bool IsStatic {
439 get { return tc.IsStatic; }
442 public ModuleContainer Module {
443 get { return tc.Module; }
446 public string GetSignatureForError ()
448 return tc.GetSignatureForError ();
451 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
456 public FullNamedExpression LookupNamespaceAlias (string name)
458 return tc.Parent.LookupNamespaceAlias (name);
461 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
464 var tp = CurrentTypeParameters;
466 TypeParameter t = tp.Find (name);
468 return new TypeParameterExpr (t, loc);
472 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
482 GetHashCode = 1 << 1,
483 HasStaticFieldInitializer = 1 << 2
486 readonly List<MemberCore> members;
488 // Holds a list of fields that have initializers
489 protected List<FieldInitializer> initialized_fields;
491 // Holds a list of static fields that have initializers
492 protected List<FieldInitializer> initialized_static_fields;
494 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
496 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
499 // Points to the first non-static field added to the container.
501 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
502 // and the first one's as good as any.
504 protected FieldBase first_nonstatic_field;
507 // This one is computed after we can distinguish interfaces
508 // from classes from the arraylist `type_bases'
510 protected TypeSpec base_type;
511 FullNamedExpression base_type_expr; // TODO: It's temporary variable
512 protected TypeSpec[] iface_exprs;
514 protected List<FullNamedExpression> type_bases;
516 // Partial parts for classes only
517 List<TypeDefinition> class_partial_parts;
519 TypeDefinition InTransit;
521 public TypeBuilder TypeBuilder;
522 GenericTypeParameterBuilder[] all_tp_builders;
524 // All recursive type parameters put together sharing same
525 // TypeParameter instances
527 TypeParameters all_type_parameters;
529 public const string DefaultIndexerName = "Item";
531 bool has_normal_indexers;
533 protected bool requires_delayed_unmanagedtype_check;
535 bool members_defined;
536 bool members_defined_ok;
537 protected bool has_static_constructor;
539 private CachedMethods cached_method;
541 protected TypeSpec spec;
542 TypeSpec current_type;
544 public int DynamicSitesCounter;
545 public int AnonymousMethodsCounter;
546 public int MethodGroupsCounter;
548 static readonly string[] attribute_targets = new [] { "type" };
549 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
552 /// The pending methods that need to be implemented
553 // (interfaces or abstract methods)
555 PendingImplementation pending;
557 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
558 : base (parent, name, attrs, kind)
560 PartialContainer = this;
561 members = new List<MemberCore> ();
566 public List<FullNamedExpression> BaseTypeExpressions {
572 public override TypeSpec CurrentType {
574 if (current_type == null) {
575 if (IsGenericOrParentIsGeneric) {
577 // Switch to inflated version as it's used by all expressions
579 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
580 current_type = spec.MakeGenericType (this, targs);
590 public override TypeParameters CurrentTypeParameters {
592 return PartialContainer.MemberName.TypeParameters;
596 int CurrentTypeParametersStartIndex {
598 int total = all_tp_builders.Length;
599 if (CurrentTypeParameters != null) {
600 return total - CurrentTypeParameters.Count;
606 public virtual AssemblyDefinition DeclaringAssembly {
608 return Module.DeclaringAssembly;
612 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
614 return Module.DeclaringAssembly;
618 public TypeSpec Definition {
624 public bool HasMembersDefined {
626 return members_defined;
630 public bool HasInstanceConstructor {
632 return (caching_flags & Flags.HasInstanceConstructor) != 0;
635 caching_flags |= Flags.HasInstanceConstructor;
639 // Indicated whether container has StructLayout attribute set Explicit
640 public bool HasExplicitLayout {
641 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
642 set { caching_flags |= Flags.HasExplicitLayout; }
645 public bool HasOperators {
647 return (caching_flags & Flags.HasUserOperators) != 0;
650 caching_flags |= Flags.HasUserOperators;
654 public bool HasStructLayout {
655 get { return (caching_flags & Flags.HasStructLayout) != 0; }
656 set { caching_flags |= Flags.HasStructLayout; }
659 public TypeSpec[] Interfaces {
665 public bool IsGenericOrParentIsGeneric {
667 return all_type_parameters != null;
671 public bool IsTopLevel {
673 return !(Parent is TypeDefinition);
677 public bool IsPartial {
679 return (ModFlags & Modifiers.PARTIAL) != 0;
683 bool ITypeDefinition.IsTypeForwarder {
689 bool ITypeDefinition.IsCyclicTypeForwarder {
696 // Returns true for secondary partial containers
700 return PartialContainer != this;
704 public MemberCache MemberCache {
706 return spec.MemberCache;
710 public List<MemberCore> Members {
716 string ITypeDefinition.Namespace {
719 while (p.Kind != MemberKind.Namespace)
722 return p.MemberName == null ? null : p.GetSignatureForError ();
726 public ParametersCompiled PrimaryConstructorParameters { get; set; }
728 public Arguments PrimaryConstructorBaseArguments { get; set; }
730 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
732 public TypeParameters TypeParametersAll {
734 return all_type_parameters;
738 public override string[] ValidAttributeTargets {
740 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
746 public override void Accept (StructuralVisitor visitor)
748 visitor.Visit (this);
751 public void AddMember (MemberCore symbol)
753 if (symbol.MemberName.ExplicitInterface != null) {
754 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
755 Report.Error (541, symbol.Location,
756 "`{0}': explicit interface declaration can only be declared in a class or struct",
757 symbol.GetSignatureForError ());
761 AddNameToContainer (symbol, symbol.MemberName.Name);
762 members.Add (symbol);
765 public override void AddTypeContainer (TypeContainer tc)
767 AddNameToContainer (tc, tc.MemberName.Basename);
769 base.AddTypeContainer (tc);
772 protected override void AddTypeContainerMember (TypeContainer tc)
776 if (containers == null)
777 containers = new List<TypeContainer> ();
779 base.AddTypeContainerMember (tc);
783 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
785 public virtual void AddNameToContainer (MemberCore symbol, string name)
787 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
791 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
792 PartialContainer.defined_names.Add (name, symbol);
796 if (symbol.EnableOverloadChecks (mc))
799 InterfaceMemberBase im = mc as InterfaceMemberBase;
800 if (im != null && im.IsExplicitImpl)
803 Report.SymbolRelatedToPreviousError (mc);
804 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
805 Error_MissingPartialModifier (symbol);
809 if (symbol is TypeParameter) {
810 Report.Error (692, symbol.Location,
811 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
813 Report.Error (102, symbol.Location,
814 "The type `{0}' already contains a definition for `{1}'",
815 GetSignatureForError (), name);
821 public void AddConstructor (Constructor c)
823 AddConstructor (c, false);
826 public void AddConstructor (Constructor c, bool isDefault)
828 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
830 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
832 if (is_static && c.ParameterInfo.IsEmpty) {
833 PartialContainer.has_static_constructor = true;
835 PartialContainer.HasInstanceConstructor = true;
841 public bool AddField (FieldBase field)
845 if ((field.ModFlags & Modifiers.STATIC) != 0)
848 var first_field = PartialContainer.first_nonstatic_field;
849 if (first_field == null) {
850 PartialContainer.first_nonstatic_field = field;
854 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
855 Report.SymbolRelatedToPreviousError (first_field.Parent);
856 Report.Warning (282, 3, field.Location,
857 "struct instance field `{0}' found in different declaration from instance field `{1}'",
858 field.GetSignatureForError (), first_field.GetSignatureForError ());
864 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
866 public void AddIndexer (Indexer i)
871 public void AddOperator (Operator op)
873 PartialContainer.HasOperators = true;
877 public void AddPartialPart (TypeDefinition part)
879 if (Kind != MemberKind.Class)
882 if (class_partial_parts == null)
883 class_partial_parts = new List<TypeDefinition> ();
885 class_partial_parts.Add (part);
888 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
890 if (a.Target == AttributeTargets.Method) {
891 foreach (var m in members) {
892 var c = m as Constructor;
896 if (c.IsPrimaryConstructor) {
897 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
902 throw new InternalErrorException ();
905 if (has_normal_indexers && a.Type == pa.DefaultMember) {
906 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
910 if (a.Type == pa.Required) {
911 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
915 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
918 public override AttributeTargets AttributeTargets {
920 throw new NotSupportedException ();
924 public TypeSpec BaseType {
926 return spec.BaseType;
930 protected virtual TypeAttributes TypeAttr {
932 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
936 public int TypeParametersCount {
938 return MemberName.Arity;
942 TypeParameterSpec[] ITypeDefinition.TypeParameters {
944 return PartialContainer.CurrentTypeParameters.Types;
948 public string GetAttributeDefaultMember ()
950 return indexer_name ?? DefaultIndexerName;
953 public bool IsComImport {
955 if (OptAttributes == null)
958 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
962 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
965 PartialContainer.RegisterFieldForInitialization (field, expression);
967 if ((field.ModFlags & Modifiers.STATIC) != 0){
968 if (initialized_static_fields == null) {
969 HasStaticFieldInitializer = true;
970 initialized_static_fields = new List<FieldInitializer> (4);
973 initialized_static_fields.Add (expression);
975 if (Kind == MemberKind.Struct) {
976 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
977 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
978 GetSignatureForError ());
982 if (initialized_fields == null)
983 initialized_fields = new List<FieldInitializer> (4);
985 initialized_fields.Add (expression);
989 public void ResolveFieldInitializers (BlockContext ec)
991 Debug.Assert (!IsPartialPart);
994 if (initialized_static_fields == null)
997 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
999 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1000 for (i = 0; i < initialized_static_fields.Count; ++i) {
1001 FieldInitializer fi = initialized_static_fields [i];
1002 ExpressionStatement s = fi.ResolveStatement (ec);
1004 s = EmptyExpressionStatement.Instance;
1005 } else if (!fi.IsSideEffectFree) {
1006 has_complex_initializer = true;
1012 for (i = 0; i < initialized_static_fields.Count; ++i) {
1013 FieldInitializer fi = initialized_static_fields [i];
1015 // Need special check to not optimize code like this
1016 // static int a = b = 5;
1017 // static int b = 0;
1019 if (!has_complex_initializer && fi.IsDefaultInitializer)
1022 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1023 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1029 if (initialized_fields == null)
1032 for (int i = 0; i < initialized_fields.Count; ++i) {
1033 FieldInitializer fi = initialized_fields [i];
1036 // Clone before resolving otherwise when field initializer is needed
1037 // in more than 1 constructor any resolve after the initial one would
1038 // only took the resolved expression which is problem for expressions
1039 // that generate extra expressions or code during Resolve phase
1041 var cloned = fi.Clone (new CloneContext ());
1043 ExpressionStatement s = fi.ResolveStatement (ec);
1045 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1050 // Field is re-initialized to its default value => removed
1052 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1055 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1056 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1057 initialized_fields [i] = (FieldInitializer) cloned;
1061 public override string DocComment {
1073 public PendingImplementation PendingImplementations {
1074 get { return pending; }
1077 internal override void GenerateDocComment (DocumentationBuilder builder)
1082 base.GenerateDocComment (builder);
1084 foreach (var member in members)
1085 member.GenerateDocComment (builder);
1088 public TypeSpec GetAttributeCoClass ()
1090 if (OptAttributes == null)
1093 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1097 return a.GetCoClassAttributeValue ();
1100 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1103 if (OptAttributes != null) {
1104 a = OptAttributes.Search (pa);
1110 return a.GetAttributeUsageAttribute ();
1113 public virtual CompilationSourceFile GetCompilationSourceFile ()
1115 TypeContainer ns = Parent;
1117 var sf = ns as CompilationSourceFile;
1125 public override string GetSignatureForMetadata ()
1127 if (Parent is TypeDefinition) {
1128 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1131 return base.GetSignatureForMetadata ();
1134 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1136 type_bases = baseTypes;
1140 /// This function computes the Base class and also the
1141 /// list of interfaces that the class or struct @c implements.
1143 /// The return value is an array (might be null) of
1144 /// interfaces implemented (as Types).
1146 /// The @base_class argument is set to the base object or null
1147 /// if this is `System.Object'.
1149 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1152 if (type_bases == null)
1155 int count = type_bases.Count;
1156 TypeSpec[] ifaces = null;
1157 var base_context = new BaseContext (this);
1158 for (int i = 0, j = 0; i < count; i++){
1159 FullNamedExpression fne = type_bases [i];
1161 var fne_resolved = fne.ResolveAsType (base_context);
1162 if (fne_resolved == null)
1165 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1166 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1167 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1168 GetSignatureForError ());
1173 base_type = fne_resolved;
1179 ifaces = new TypeSpec [count - i];
1181 if (fne_resolved.IsInterface) {
1182 for (int ii = 0; ii < j; ++ii) {
1183 if (fne_resolved == ifaces [ii]) {
1184 Report.Error (528, Location, "`{0}' is already listed in interface list",
1185 fne_resolved.GetSignatureForError ());
1190 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1191 Report.Error (61, fne.Location,
1192 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1193 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1196 Report.SymbolRelatedToPreviousError (fne_resolved);
1197 if (Kind != MemberKind.Class) {
1198 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1199 } else if (base_class != null)
1200 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1201 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1203 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1204 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1208 ifaces [j++] = fne_resolved;
1215 // Checks that some operators come in pairs:
1221 // They are matched based on the return type and the argument types
1223 void CheckPairedOperators ()
1225 bool has_equality_or_inequality = false;
1226 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1228 for (int i = 0; i < members.Count; ++i) {
1229 var o_a = members[i] as Operator;
1233 var o_type = o_a.OperatorType;
1234 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1235 has_equality_or_inequality = true;
1237 if (found_matched.Contains (o_type))
1240 var matching_type = o_a.GetMatchingOperator ();
1241 if (matching_type == Operator.OpType.TOP) {
1245 bool pair_found = false;
1246 for (int ii = 0; ii < members.Count; ++ii) {
1247 var o_b = members[ii] as Operator;
1248 if (o_b == null || o_b.OperatorType != matching_type)
1251 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1254 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1257 found_matched.Add (matching_type);
1263 Report.Error (216, o_a.Location,
1264 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1265 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1269 if (has_equality_or_inequality) {
1271 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1272 GetSignatureForError ());
1274 if (!HasGetHashCode)
1275 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1276 GetSignatureForError ());
1280 public override void CreateMetadataName (StringBuilder sb)
1282 if (Parent.MemberName != null) {
1283 Parent.CreateMetadataName (sb);
1285 if (sb.Length != 0) {
1290 sb.Append (MemberName.Basename);
1293 bool CreateTypeBuilder ()
1296 // Sets .size to 1 for structs with no instance fields
1298 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1300 var parent_def = Parent as TypeDefinition;
1301 if (parent_def == null) {
1302 var sb = new StringBuilder ();
1303 CreateMetadataName (sb);
1304 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1306 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1309 if (DeclaringAssembly.Importer != null)
1310 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1312 spec.SetMetaInfo (TypeBuilder);
1313 spec.MemberCache = new MemberCache (this);
1315 TypeParameters parentAllTypeParameters = null;
1316 if (parent_def != null) {
1317 spec.DeclaringType = Parent.CurrentType;
1318 parent_def.MemberCache.AddMember (spec);
1319 parentAllTypeParameters = parent_def.all_type_parameters;
1322 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1323 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1325 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1327 if (CurrentTypeParameters != null) {
1328 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1329 CurrentTypeParameters.Define (all_tp_builders);
1336 public static string FilterNestedName (string name)
1339 // SRE API does not handle namespaces and types separately but
1340 // determine that from '.' in name. That's problematic because
1341 // dot is valid character for type name. By replacing any '.'
1342 // in name we avoid any ambiguities and never emit metadata
1343 // namespace for nested types
1345 return name.Replace ('.', '_');
1348 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1351 int parent_offset = 0;
1352 if (parentAllTypeParameters != null) {
1353 if (CurrentTypeParameters == null) {
1354 all_type_parameters = parentAllTypeParameters;
1355 return parentAllTypeParameters.GetAllNames ();
1358 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1359 all_type_parameters = new TypeParameters (names.Length);
1360 all_type_parameters.Add (parentAllTypeParameters);
1362 parent_offset = all_type_parameters.Count;
1363 for (int i = 0; i < parent_offset; ++i)
1364 names[i] = all_type_parameters[i].MemberName.Name;
1367 names = new string[CurrentTypeParameters.Count];
1370 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1371 if (all_type_parameters != null)
1372 all_type_parameters.Add (MemberName.TypeParameters[i]);
1374 var name = CurrentTypeParameters[i].MemberName.Name;
1375 names[parent_offset + i] = name;
1376 for (int ii = 0; ii < parent_offset + i; ++ii) {
1377 if (names[ii] != name)
1380 var tp = CurrentTypeParameters[i];
1381 var conflict = all_type_parameters[ii];
1383 tp.WarningParentNameConflict (conflict);
1387 if (all_type_parameters == null)
1388 all_type_parameters = CurrentTypeParameters;
1394 public SourceMethodBuilder CreateMethodSymbolEntry ()
1396 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1399 var source_file = GetCompilationSourceFile ();
1400 if (source_file == null)
1403 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1407 // Creates a proxy base method call inside this container for hoisted base member calls
1409 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1411 Method proxy_method;
1414 // One proxy per base method is enough
1416 if (hoisted_base_call_proxies == null) {
1417 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1418 proxy_method = null;
1420 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1423 if (proxy_method == null) {
1424 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1426 MemberName member_name;
1427 TypeArguments targs = null;
1428 TypeSpec return_type = method.ReturnType;
1429 var local_param_types = method.Parameters.Types;
1431 if (method.IsGeneric) {
1433 // Copy all base generic method type parameters info
1435 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1436 var tparams = new TypeParameters ();
1438 targs = new TypeArguments ();
1439 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1440 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1441 var tp = hoisted_tparams[i];
1442 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1443 tparams.Add (local_tp);
1445 targs.Add (new SimpleName (tp.Name, Location));
1446 targs.Arguments[i] = local_tp.Type;
1449 member_name = new MemberName (name, tparams, Location);
1452 // Mutate any method type parameters from original
1453 // to newly created hoisted version
1455 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1456 return_type = mutator.Mutate (return_type);
1457 local_param_types = mutator.Mutate (local_param_types);
1459 member_name = new MemberName (name);
1462 var base_parameters = new Parameter[method.Parameters.Count];
1463 for (int i = 0; i < base_parameters.Length; ++i) {
1464 var base_param = method.Parameters.FixedParameters[i];
1465 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1466 base_param.Name, base_param.ModFlags, null, Location);
1467 base_parameters[i].Resolve (this, i);
1470 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1471 if (method.Parameters.HasArglist) {
1472 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1473 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1476 // Compiler generated proxy
1477 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1478 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1479 member_name, cloned_params, null);
1481 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1482 IsCompilerGenerated = true
1485 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1486 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1488 mg.SetTypeArguments (rc, targs);
1490 // Get all the method parameters and pass them as arguments
1491 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1492 Statement statement;
1493 if (method.ReturnType.Kind == MemberKind.Void)
1494 statement = new StatementExpression (real_base_call);
1496 statement = new Return (real_base_call, Location);
1498 block.AddStatement (statement);
1499 proxy_method.Block = block;
1501 members.Add (proxy_method);
1502 proxy_method.Define ();
1503 proxy_method.PrepareEmit ();
1505 hoisted_base_call_proxies.Add (method, proxy_method);
1508 return proxy_method.Spec;
1511 protected bool DefineBaseTypes ()
1513 if (IsPartialPart && Kind == MemberKind.Class)
1516 return DoDefineBaseType ();
1519 bool DoDefineBaseType ()
1521 iface_exprs = ResolveBaseTypes (out base_type_expr);
1524 if (IsPartialPart) {
1525 set_base_type = false;
1527 if (base_type_expr != null) {
1528 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1529 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1530 Report.Error (263, Location,
1531 "Partial declarations of `{0}' must not specify different base classes",
1532 GetSignatureForError ());
1534 PartialContainer.base_type_expr = base_type_expr;
1535 PartialContainer.base_type = base_type;
1536 set_base_type = true;
1540 if (iface_exprs != null) {
1541 if (PartialContainer.iface_exprs == null)
1542 PartialContainer.iface_exprs = iface_exprs;
1544 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1545 foreach (var iface_partial in iface_exprs) {
1546 if (ifaces.Contains (iface_partial))
1549 ifaces.Add (iface_partial);
1552 PartialContainer.iface_exprs = ifaces.ToArray ();
1556 PartialContainer.members.AddRange (members);
1557 if (containers != null) {
1558 if (PartialContainer.containers == null)
1559 PartialContainer.containers = new List<TypeContainer> ();
1561 PartialContainer.containers.AddRange (containers);
1564 if (PrimaryConstructorParameters != null) {
1565 if (PartialContainer.PrimaryConstructorParameters != null) {
1566 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1568 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1572 members_defined = members_defined_ok = true;
1573 caching_flags |= Flags.CloseTypeCreated;
1575 set_base_type = true;
1578 var cycle = CheckRecursiveDefinition (this);
1579 if (cycle != null) {
1580 Report.SymbolRelatedToPreviousError (cycle);
1581 if (this is Interface) {
1582 Report.Error (529, Location,
1583 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1584 GetSignatureForError (), cycle.GetSignatureForError ());
1587 PartialContainer.iface_exprs = null;
1589 Report.Error (146, Location,
1590 "Circular base class dependency involving `{0}' and `{1}'",
1591 GetSignatureForError (), cycle.GetSignatureForError ());
1594 PartialContainer.base_type = null;
1598 if (iface_exprs != null) {
1599 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1600 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1603 foreach (var iface_type in iface_exprs) {
1604 // Prevents a crash, the interface might not have been resolved: 442144
1605 if (iface_type == null)
1608 if (!spec.AddInterfaceDefined (iface_type))
1611 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1615 if (Kind == MemberKind.Interface) {
1616 spec.BaseType = Compiler.BuiltinTypes.Object;
1620 if (set_base_type) {
1625 // Base type of partial container has to be resolved before we
1626 // resolve any nested types of the container. We need to know
1627 // partial parts because the base type can be specified in file
1628 // defined after current container
1630 if (class_partial_parts != null) {
1631 foreach (var pp in class_partial_parts) {
1632 if (pp.PrimaryConstructorBaseArguments != null)
1633 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1635 pp.DoDefineBaseType ();
1645 if (base_type == null) {
1646 TypeBuilder.SetParent (null);
1650 if (spec.BaseType == base_type)
1653 spec.BaseType = base_type;
1656 spec.UpdateInflatedInstancesBaseType ();
1658 // Set base type after type creation
1659 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1662 public override void ExpandBaseInterfaces ()
1665 DoExpandBaseInterfaces ();
1667 base.ExpandBaseInterfaces ();
1670 public void DoExpandBaseInterfaces ()
1672 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1675 caching_flags |= Flags.InterfacesExpanded;
1678 // Expand base interfaces. It cannot be done earlier because all partial
1679 // interface parts need to be defined before the type they are used from
1681 if (iface_exprs != null) {
1682 foreach (var iface in iface_exprs) {
1686 var td = iface.MemberDefinition as TypeDefinition;
1688 td.DoExpandBaseInterfaces ();
1690 if (iface.Interfaces == null)
1693 foreach (var biface in iface.Interfaces) {
1694 if (spec.AddInterfaceDefined (biface)) {
1695 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1702 // Include all base type interfaces too, see ImportTypeBase for details
1704 if (base_type != null) {
1705 var td = base_type.MemberDefinition as TypeDefinition;
1707 td.DoExpandBaseInterfaces ();
1710 // Simply use base interfaces only, they are all expanded which makes
1711 // it easy to handle generic type argument propagation with single
1714 // interface IA<T> : IB<T>
1715 // interface IB<U> : IC<U>
1718 if (base_type.Interfaces != null) {
1719 foreach (var iface in base_type.Interfaces) {
1720 spec.AddInterfaceDefined (iface);
1726 public override void PrepareEmit ()
1728 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1731 foreach (var member in members) {
1732 var pbm = member as PropertyBasedMember;
1738 var mc = member as MethodCore;
1744 var c = member as Const;
1749 base.PrepareEmit ();
1753 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1755 public override bool CreateContainer ()
1757 if (TypeBuilder != null)
1763 if (IsPartialPart) {
1764 spec = PartialContainer.spec;
1765 TypeBuilder = PartialContainer.TypeBuilder;
1766 all_tp_builders = PartialContainer.all_tp_builders;
1767 all_type_parameters = PartialContainer.all_type_parameters;
1769 if (!CreateTypeBuilder ()) {
1775 return base.CreateContainer ();
1778 protected override void DoDefineContainer ()
1782 DoResolveTypeParameters ();
1786 // Replaces normal spec with predefined one when compiling corlib
1787 // and this type container defines predefined type
1789 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1791 // When compiling build-in types we start with two
1792 // version of same type. One is of BuiltinTypeSpec and
1793 // second one is ordinary TypeSpec. The unification
1794 // happens at later stage when we know which type
1795 // really matches the builtin type signature. However
1796 // that means TypeSpec create during CreateType of this
1797 // type has to be replaced with builtin one
1799 spec.SetMetaInfo (TypeBuilder);
1800 spec.MemberCache = this.spec.MemberCache;
1801 spec.DeclaringType = this.spec.DeclaringType;
1804 current_type = null;
1805 if (class_partial_parts != null) {
1806 foreach (var part in class_partial_parts)
1811 public override void RemoveContainer (TypeContainer cont)
1813 base.RemoveContainer (cont);
1814 Members.Remove (cont);
1815 Cache.Remove (cont.MemberName.Basename);
1818 protected virtual bool DoResolveTypeParameters ()
1820 var tparams = MemberName.TypeParameters;
1821 if (tparams == null)
1824 var base_context = new BaseContext (this);
1825 for (int i = 0; i < tparams.Count; ++i) {
1826 var tp = tparams[i];
1828 if (!tp.ResolveConstraints (base_context)) {
1833 if (IsPartialPart) {
1834 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1836 tp.Create (spec, this);
1839 if (tp.OptAttributes != null) {
1840 if (pc_tp.OptAttributes == null)
1841 pc_tp.OptAttributes = tp.OptAttributes;
1843 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1848 if (IsPartialPart) {
1849 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1855 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1857 if (InTransit != null)
1862 if (base_type != null) {
1863 var ptc = base_type.MemberDefinition as TypeDefinition;
1864 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1868 if (iface_exprs != null) {
1869 foreach (var iface in iface_exprs) {
1870 // the interface might not have been resolved, prevents a crash, see #442144
1873 var ptc = iface.MemberDefinition as Interface;
1874 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1879 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1887 /// Populates our TypeBuilder with fields and methods
1889 public sealed override bool Define ()
1891 if (members_defined)
1892 return members_defined_ok;
1894 members_defined_ok = DoDefineMembers ();
1895 members_defined = true;
1899 return members_defined_ok;
1902 protected virtual bool DoDefineMembers ()
1904 Debug.Assert (!IsPartialPart);
1906 if (iface_exprs != null) {
1907 foreach (var iface_type in iface_exprs) {
1908 if (iface_type == null)
1911 // Ensure the base is always setup
1912 var compiled_iface = iface_type.MemberDefinition as Interface;
1913 if (compiled_iface != null)
1914 compiled_iface.Define ();
1916 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1917 if (oa != null && !IsObsolete)
1918 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1920 if (iface_type.Arity > 0) {
1921 // TODO: passing `this' is wrong, should be base type iface instead
1922 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1924 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1925 Report.Error (1966, Location,
1926 "`{0}': cannot implement a dynamic interface `{1}'",
1927 GetSignatureForError (), iface_type.GetSignatureForError ());
1932 if (iface_type.IsGenericOrParentIsGeneric) {
1933 foreach (var prev_iface in iface_exprs) {
1934 if (prev_iface == iface_type || prev_iface == null)
1937 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1940 Report.Error (695, Location,
1941 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1942 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1947 if (Kind == MemberKind.Interface) {
1948 foreach (var iface in spec.Interfaces) {
1949 MemberCache.AddInterface (iface);
1954 if (base_type != null) {
1956 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1958 if (base_type_expr != null) {
1959 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1960 if (obsolete_attr != null && !IsObsolete)
1961 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1963 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1964 Report.Error (698, base_type_expr.Location,
1965 "A generic type cannot derive from `{0}' because it is an attribute class",
1966 base_type.GetSignatureForError ());
1970 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1971 if (baseContainer != null) {
1972 baseContainer.Define ();
1975 // It can trigger define of this type (for generic types only)
1977 if (HasMembersDefined)
1982 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1983 pending = PendingImplementation.GetPendingImplementations (this);
1986 var count = members.Count;
1987 for (int i = 0; i < count; ++i) {
1988 var mc = members[i] as InterfaceMemberBase;
1989 if (mc == null || !mc.IsExplicitImpl)
1994 } catch (Exception e) {
1995 throw new InternalErrorException (mc, e);
1999 for (int i = 0; i < count; ++i) {
2000 var mc = members[i] as InterfaceMemberBase;
2001 if (mc != null && mc.IsExplicitImpl)
2004 if (members[i] is TypeContainer)
2008 members[i].Define ();
2009 } catch (Exception e) {
2010 throw new InternalErrorException (members[i], e);
2015 CheckPairedOperators ();
2018 if (requires_delayed_unmanagedtype_check) {
2019 requires_delayed_unmanagedtype_check = false;
2020 foreach (var member in members) {
2021 var f = member as Field;
2022 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2023 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2027 ComputeIndexerName();
2029 if (HasEquals && !HasGetHashCode) {
2030 Report.Warning (659, 3, Location,
2031 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2034 if (Kind == MemberKind.Interface && iface_exprs != null) {
2035 MemberCache.RemoveHiddenMembers (spec);
2041 void ComputeIndexerName ()
2043 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2044 if (indexers == null)
2047 string class_indexer_name = null;
2050 // Check normal indexers for consistent name, explicit interface implementation
2051 // indexers are ignored
2053 foreach (var indexer in indexers) {
2055 // FindMembers can return unfiltered full hierarchy names
2057 if (indexer.DeclaringType != spec)
2060 has_normal_indexers = true;
2062 if (class_indexer_name == null) {
2063 indexer_name = class_indexer_name = indexer.Name;
2067 if (indexer.Name != class_indexer_name)
2068 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2069 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2073 void EmitIndexerName ()
2075 if (!has_normal_indexers)
2078 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2082 var encoder = new AttributeEncoder ();
2083 encoder.Encode (GetAttributeDefaultMember ());
2084 encoder.EncodeEmptyNamedArguments ();
2086 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2089 public override void VerifyMembers ()
2092 // Check for internal or private fields that were never assigned
2094 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2095 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2096 foreach (var member in members) {
2097 if (member is Event) {
2099 // An event can be assigned from same class only, report
2100 // this warning for all accessibility modes
2102 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2103 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2108 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2109 if (is_type_exposed)
2112 member.SetIsUsed ();
2115 var f = member as Field;
2119 if (!member.IsUsed) {
2120 if (!PartialContainer.HasStructLayout) {
2121 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2122 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2124 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2125 member.GetSignatureForError ());
2132 if ((f.caching_flags & Flags.IsAssigned) != 0)
2136 // Only report 649 on level 4
2138 if (Compiler.Settings.WarningLevel < 4)
2142 // Don't be pedantic when type requires specific layout
2144 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2147 Constant c = New.Constantify (f.MemberType, f.Location);
2150 value = c.GetValueAsLiteral ();
2151 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2158 value = " `" + value + "'";
2160 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2161 f.GetSignatureForError (), value);
2165 base.VerifyMembers ();
2168 public override void Emit ()
2170 if (OptAttributes != null)
2171 OptAttributes.Emit ();
2173 if (!IsCompilerGenerated) {
2175 MemberSpec candidate;
2176 bool overrides = false;
2177 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2178 if (conflict_symbol == null && candidate == null) {
2179 if ((ModFlags & Modifiers.NEW) != 0)
2180 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2181 GetSignatureForError ());
2183 if ((ModFlags & Modifiers.NEW) == 0) {
2184 if (candidate == null)
2185 candidate = conflict_symbol;
2187 Report.SymbolRelatedToPreviousError (candidate);
2188 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2189 GetSignatureForError (), candidate.GetSignatureForError ());
2194 // Run constraints check on all possible generic types
2195 if (base_type != null && base_type_expr != null) {
2196 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2199 if (iface_exprs != null) {
2200 foreach (var iface_type in iface_exprs) {
2201 if (iface_type == null)
2204 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2209 if (all_tp_builders != null) {
2210 int current_starts_index = CurrentTypeParametersStartIndex;
2211 for (int i = 0; i < all_tp_builders.Length; i++) {
2212 if (i < current_starts_index) {
2213 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2215 var tp = CurrentTypeParameters [i - current_starts_index];
2216 tp.CheckGenericConstraints (!IsObsolete);
2222 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2223 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2226 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2227 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2232 for (int i = 0; i < members.Count; i++) {
2234 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2241 CheckAttributeClsCompliance ();
2243 if (pending != null)
2244 pending.VerifyPendingMethods ();
2248 void CheckAttributeClsCompliance ()
2250 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2253 foreach (var m in members) {
2254 var c = m as Constructor;
2258 if (c.HasCompliantArgs)
2262 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2265 public sealed override void EmitContainer ()
2267 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2273 public override void CloseContainer ()
2275 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2278 // Close base type container first to avoid TypeLoadException
2279 if (spec.BaseType != null) {
2280 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2281 if (btype != null) {
2282 btype.CloseContainer ();
2284 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2290 caching_flags |= Flags.CloseTypeCreated;
2291 TypeBuilder.CreateType ();
2292 } catch (TypeLoadException) {
2294 // This is fine, the code still created the type
2296 } catch (Exception e) {
2297 throw new InternalErrorException (this, e);
2300 base.CloseContainer ();
2303 initialized_fields = null;
2304 initialized_static_fields = null;
2306 OptAttributes = null;
2310 // Performs the validation on a Method's modifiers (properties have
2311 // the same properties).
2313 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2315 public bool MethodModifiersValid (MemberCore mc)
2317 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2318 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2320 var flags = mc.ModFlags;
2323 // At most one of static, virtual or override
2325 if ((flags & Modifiers.STATIC) != 0){
2326 if ((flags & vao) != 0){
2327 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2328 mc.GetSignatureForError ());
2333 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2334 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2335 mc.GetSignatureForError ());
2340 // If the declaration includes the abstract modifier, then the
2341 // declaration does not include static, virtual or extern
2343 if ((flags & Modifiers.ABSTRACT) != 0){
2344 if ((flags & Modifiers.EXTERN) != 0){
2346 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2350 if ((flags & Modifiers.SEALED) != 0) {
2351 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2355 if ((flags & Modifiers.VIRTUAL) != 0){
2356 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2360 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2361 Report.SymbolRelatedToPreviousError (this);
2362 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2363 mc.GetSignatureForError (), GetSignatureForError ());
2368 if ((flags & Modifiers.PRIVATE) != 0){
2369 if ((flags & vao) != 0){
2370 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2375 if ((flags & Modifiers.SEALED) != 0){
2376 if ((flags & Modifiers.OVERRIDE) == 0){
2377 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2385 protected override bool VerifyClsCompliance ()
2387 if (!base.VerifyClsCompliance ())
2390 // Check all container names for user classes
2391 if (Kind != MemberKind.Delegate)
2392 MemberCache.VerifyClsCompliance (Definition, Report);
2394 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2395 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2396 GetSignatureForError (), BaseType.GetSignatureForError ());
2402 /// Performs checks for an explicit interface implementation. First it
2403 /// checks whether the `interface_type' is a base inteface implementation.
2404 /// Then it checks whether `name' exists in the interface type.
2406 public bool VerifyImplements (InterfaceMemberBase mb)
2408 var ifaces = PartialContainer.Interfaces;
2409 if (ifaces != null) {
2410 foreach (TypeSpec t in ifaces){
2411 if (t == mb.InterfaceType)
2414 var expanded_base = t.Interfaces;
2415 if (expanded_base == null)
2418 foreach (var bt in expanded_base) {
2419 if (bt == mb.InterfaceType)
2425 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2426 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2427 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2432 // Used for visiblity checks to tests whether this definition shares
2433 // base type baseType, it does member-definition search
2435 public bool IsBaseTypeDefinition (TypeSpec baseType)
2437 // RootContext check
2438 if (TypeBuilder == null)
2443 if (type.MemberDefinition == baseType.MemberDefinition)
2446 type = type.BaseType;
2447 } while (type != null);
2452 public override bool IsClsComplianceRequired ()
2455 return PartialContainer.IsClsComplianceRequired ();
2457 return base.IsClsComplianceRequired ();
2460 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2462 return Module.DeclaringAssembly == assembly;
2465 public virtual bool IsUnmanagedType ()
2470 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2472 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2476 // Public function used to locate types.
2478 // Returns: Type or null if they type can not be found.
2480 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2482 FullNamedExpression e;
2483 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2489 var tp = CurrentTypeParameters;
2491 TypeParameter tparam = tp.Find (name);
2493 e = new TypeParameterExpr (tparam, Location.Null);
2498 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2500 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2501 e = new TypeExpression (t, Location.Null);
2503 var errors = Compiler.Report.Errors;
2504 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2506 // TODO: LookupNamespaceOrType does more than just lookup. The result
2507 // cannot be cached or the error reporting won't happen
2508 if (errors != Compiler.Report.Errors)
2513 // TODO MemberCache: How to cache arity stuff ?
2514 if (arity == 0 && mode == LookupMode.Normal)
2520 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2522 // Has any nested type
2523 // Does not work, because base type can have
2524 //if (PartialContainer.Types == null)
2527 var container = PartialContainer.CurrentType;
2528 return MemberCache.FindNestedType (container, name, arity);
2531 public void Mark_HasEquals ()
2533 cached_method |= CachedMethods.Equals;
2536 public void Mark_HasGetHashCode ()
2538 cached_method |= CachedMethods.GetHashCode;
2541 public override void WriteDebugSymbol (MonoSymbolFile file)
2546 foreach (var m in members) {
2547 m.WriteDebugSymbol (file);
2552 /// Method container contains Equals method
2554 public bool HasEquals {
2556 return (cached_method & CachedMethods.Equals) != 0;
2561 /// Method container contains GetHashCode method
2563 public bool HasGetHashCode {
2565 return (cached_method & CachedMethods.GetHashCode) != 0;
2569 public bool HasStaticFieldInitializer {
2571 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2575 cached_method |= CachedMethods.HasStaticFieldInitializer;
2577 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2581 public override string DocCommentHeader {
2582 get { return "T:"; }
2586 public abstract class ClassOrStruct : TypeDefinition
2588 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2590 SecurityType declarative_security;
2591 protected Constructor generated_primary_constructor;
2593 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2594 : base (parent, name, attrs, kind)
2598 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2600 protected override TypeAttributes TypeAttr {
2602 TypeAttributes ta = base.TypeAttr;
2603 if (!has_static_constructor)
2604 ta |= TypeAttributes.BeforeFieldInit;
2606 if (Kind == MemberKind.Class) {
2607 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2609 ta |= StaticClassAttribute;
2611 ta |= TypeAttributes.SequentialLayout;
2618 public override void AddNameToContainer (MemberCore symbol, string name)
2620 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2621 if (symbol is TypeParameter) {
2622 Report.Error (694, symbol.Location,
2623 "Type parameter `{0}' has same name as containing type, or method",
2624 symbol.GetSignatureForError ());
2628 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2629 if (imb == null || !imb.IsExplicitImpl) {
2630 Report.SymbolRelatedToPreviousError (this);
2631 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2632 symbol.GetSignatureForError ());
2637 base.AddNameToContainer (symbol, name);
2640 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2642 if (a.IsValidSecurityAttribute ()) {
2643 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2647 if (a.Type == pa.StructLayout) {
2648 PartialContainer.HasStructLayout = true;
2649 if (a.IsExplicitLayoutKind ())
2650 PartialContainer.HasExplicitLayout = true;
2653 if (a.Type == pa.Dynamic) {
2654 a.Error_MisusedDynamicAttribute ();
2658 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2662 /// Defines the default constructors
2664 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2666 // The default instance constructor is public
2667 // If the class is abstract, the default constructor is protected
2668 // The default static constructor is private
2671 ParametersCompiled parameters = null;
2673 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2674 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2676 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2677 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2680 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2681 if (Kind == MemberKind.Class)
2682 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2684 if (PrimaryConstructorParameters != null && !is_static) {
2685 c.IsPrimaryConstructor = true;
2686 c.caching_flags |= Flags.MethodOverloadsExist;
2689 AddConstructor (c, true);
2690 if (PrimaryConstructorBlock == null) {
2691 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2692 IsCompilerGenerated = true
2695 c.Block = PrimaryConstructorBlock;
2701 protected override bool DoDefineMembers ()
2703 CheckProtectedModifier ();
2705 if (PrimaryConstructorParameters != null) {
2707 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2708 if (p.Name == MemberName.Name) {
2709 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2710 GetSignatureForError ());
2713 if (CurrentTypeParameters != null) {
2714 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2715 var tp = CurrentTypeParameters [i];
2716 if (p.Name == tp.Name) {
2717 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2718 GetSignatureForError (), p.GetSignatureForError ());
2725 base.DoDefineMembers ();
2730 public override void Emit ()
2732 if (!has_static_constructor && HasStaticFieldInitializer) {
2733 var c = DefineDefaultConstructor (true);
2739 if (declarative_security != null) {
2740 foreach (var de in declarative_security) {
2742 TypeBuilder.__AddDeclarativeSecurity (de);
2744 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2752 public sealed class Class : ClassOrStruct
2754 const Modifiers AllowedModifiers =
2757 Modifiers.PROTECTED |
2758 Modifiers.INTERNAL |
2760 Modifiers.ABSTRACT |
2765 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2766 : base (parent, name, attrs, MemberKind.Class)
2768 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2769 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2770 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2773 public override void Accept (StructuralVisitor visitor)
2775 visitor.Visit (this);
2778 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2780 var pmn = MemberName;
2781 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2782 Report.Error (537, Location,
2783 "The class System.Object cannot have a base class or implement an interface.");
2785 base.SetBaseTypes (baseTypes);
2788 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2790 if (a.Type == pa.AttributeUsage) {
2791 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2792 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2796 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2797 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2801 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2802 a.Error_MissingGuidAttribute ();
2806 if (a.Type == pa.Extension) {
2807 a.Error_MisusedExtensionAttribute ();
2811 if (a.Type.IsConditionallyExcluded (this))
2814 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2817 public override AttributeTargets AttributeTargets {
2819 return AttributeTargets.Class;
2823 protected override bool DoDefineMembers ()
2825 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2826 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2829 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2830 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2834 if (PrimaryConstructorParameters != null) {
2835 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2836 PrimaryConstructorParameters = null;
2839 foreach (var m in Members) {
2840 if (m is Operator) {
2841 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2845 if (m is Destructor) {
2846 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2851 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2855 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2858 if (m is Constructor) {
2859 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2863 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2866 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2867 generated_primary_constructor = DefineDefaultConstructor (false);
2870 return base.DoDefineMembers ();
2873 public override void Emit ()
2877 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2878 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2880 if (base_type != null && base_type.HasDynamicElement) {
2881 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2885 public override void GetCompletionStartingWith (string prefix, List<string> results)
2887 base.GetCompletionStartingWith (prefix, results);
2890 while (bt != null) {
2891 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2896 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2898 var ifaces = base.ResolveBaseTypes (out base_class);
2900 if (base_class == null) {
2901 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2902 base_type = Compiler.BuiltinTypes.Object;
2904 if (base_type.IsGenericParameter){
2905 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2906 GetSignatureForError (), base_type.GetSignatureForError ());
2907 } else if (base_type.IsStatic) {
2908 Report.SymbolRelatedToPreviousError (base_type);
2909 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2910 GetSignatureForError (), base_type.GetSignatureForError ());
2911 } else if (base_type.IsSealed) {
2912 Report.SymbolRelatedToPreviousError (base_type);
2913 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2914 GetSignatureForError (), base_type.GetSignatureForError ());
2915 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2916 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2917 GetSignatureForError (), base_type.GetSignatureForError ());
2920 switch (base_type.BuiltinType) {
2921 case BuiltinTypeSpec.Type.Enum:
2922 case BuiltinTypeSpec.Type.ValueType:
2923 case BuiltinTypeSpec.Type.MulticastDelegate:
2924 case BuiltinTypeSpec.Type.Delegate:
2925 case BuiltinTypeSpec.Type.Array:
2926 if (!(spec is BuiltinTypeSpec)) {
2927 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2928 GetSignatureForError (), base_type.GetSignatureForError ());
2930 base_type = Compiler.BuiltinTypes.Object;
2935 if (!IsAccessibleAs (base_type)) {
2936 Report.SymbolRelatedToPreviousError (base_type);
2937 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2938 base_type.GetSignatureForError (), GetSignatureForError ());
2942 if (PartialContainer.IsStatic && ifaces != null) {
2943 foreach (var t in ifaces)
2944 Report.SymbolRelatedToPreviousError (t);
2945 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2951 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2952 /// Valid only for attribute classes.
2953 public override string[] ConditionalConditions ()
2955 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2958 caching_flags &= ~Flags.Excluded_Undetected;
2960 if (OptAttributes == null)
2963 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2967 string[] conditions = new string[attrs.Length];
2968 for (int i = 0; i < conditions.Length; ++i)
2969 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2971 caching_flags |= Flags.Excluded;
2976 public sealed class Struct : ClassOrStruct
2978 bool is_unmanaged, has_unmanaged_check_done;
2982 // Modifiers allowed in a struct declaration
2984 const Modifiers AllowedModifiers =
2987 Modifiers.PROTECTED |
2988 Modifiers.INTERNAL |
2992 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2993 : base (parent, name, attrs, MemberKind.Struct)
2995 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2996 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2997 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3000 public override AttributeTargets AttributeTargets {
3002 return AttributeTargets.Struct;
3006 public override void Accept (StructuralVisitor visitor)
3008 visitor.Visit (this);
3011 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3013 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3016 // When struct constains fixed fixed and struct layout has explicitly
3017 // set CharSet, its value has to be propagated to compiler generated
3020 if (a.Type == pa.StructLayout) {
3021 var value = a.GetNamedValue ("CharSet");
3025 for (int i = 0; i < Members.Count; ++i) {
3026 FixedField ff = Members [i] as FixedField;
3030 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3035 bool CheckStructCycles ()
3041 foreach (var member in Members) {
3042 var field = member as Field;
3046 TypeSpec ftype = field.Spec.MemberType;
3047 if (!ftype.IsStruct)
3050 if (ftype is BuiltinTypeSpec)
3053 foreach (var targ in ftype.TypeArguments) {
3054 if (!CheckFieldTypeCycle (targ)) {
3055 Report.Error (523, field.Location,
3056 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3057 field.GetSignatureForError (), ftype.GetSignatureForError ());
3063 // Static fields of exactly same type are allowed
3065 if (field.IsStatic && ftype == CurrentType)
3068 if (!CheckFieldTypeCycle (ftype)) {
3069 Report.Error (523, field.Location,
3070 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3071 field.GetSignatureForError (), ftype.GetSignatureForError ());
3080 static bool CheckFieldTypeCycle (TypeSpec ts)
3082 var fts = ts.MemberDefinition as Struct;
3086 return fts.CheckStructCycles ();
3089 protected override bool DoDefineMembers ()
3091 var res = base.DoDefineMembers ();
3093 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3094 generated_primary_constructor = DefineDefaultConstructor (false);
3095 generated_primary_constructor.Define ();
3101 public override void Emit ()
3103 CheckStructCycles ();
3108 bool HasUserDefaultConstructor ()
3110 foreach (var m in PartialContainer.Members) {
3111 var c = m as Constructor;
3115 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3122 public override bool IsUnmanagedType ()
3124 if (has_unmanaged_check_done)
3125 return is_unmanaged;
3127 if (requires_delayed_unmanagedtype_check)
3130 var parent_def = Parent.PartialContainer;
3131 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3132 has_unmanaged_check_done = true;
3136 if (first_nonstatic_field != null) {
3137 requires_delayed_unmanagedtype_check = true;
3139 foreach (var member in Members) {
3140 var f = member as Field;
3147 // It can happen when recursive unmanaged types are defined
3148 // struct S { S* s; }
3149 TypeSpec mt = f.MemberType;
3157 has_unmanaged_check_done = true;
3161 has_unmanaged_check_done = true;
3164 is_unmanaged = true;
3168 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3170 var ifaces = base.ResolveBaseTypes (out base_class);
3171 base_type = Compiler.BuiltinTypes.ValueType;
3179 public sealed class Interface : TypeDefinition {
3182 /// Modifiers allowed in a class declaration
3184 const Modifiers AllowedModifiers =
3187 Modifiers.PROTECTED |
3188 Modifiers.INTERNAL |
3192 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3193 : base (parent, name, attrs, MemberKind.Interface)
3195 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3197 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3198 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3203 public override AttributeTargets AttributeTargets {
3205 return AttributeTargets.Interface;
3209 protected override TypeAttributes TypeAttr {
3211 const TypeAttributes DefaultTypeAttributes =
3212 TypeAttributes.AutoLayout |
3213 TypeAttributes.Abstract |
3214 TypeAttributes.Interface;
3216 return base.TypeAttr | DefaultTypeAttributes;
3222 public override void Accept (StructuralVisitor visitor)
3224 visitor.Visit (this);
3227 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3229 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3230 a.Error_MissingGuidAttribute ();
3234 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3237 protected override bool VerifyClsCompliance ()
3239 if (!base.VerifyClsCompliance ())
3242 if (iface_exprs != null) {
3243 foreach (var iface in iface_exprs) {
3244 if (iface.IsCLSCompliant ())
3247 Report.SymbolRelatedToPreviousError (iface);
3248 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3249 GetSignatureForError (), iface.GetSignatureForError ());
3257 public abstract class InterfaceMemberBase : MemberBase
3260 // Common modifiers allowed in a class declaration
3262 protected const Modifiers AllowedModifiersClass =
3265 Modifiers.PROTECTED |
3266 Modifiers.INTERNAL |
3271 Modifiers.OVERRIDE |
3272 Modifiers.ABSTRACT |
3277 // Common modifiers allowed in a struct declaration
3279 protected const Modifiers AllowedModifiersStruct =
3282 Modifiers.PROTECTED |
3283 Modifiers.INTERNAL |
3286 Modifiers.OVERRIDE |
3291 // Common modifiers allowed in a interface declaration
3293 protected const Modifiers AllowedModifiersInterface =
3298 // Whether this is an interface member.
3300 public bool IsInterface;
3303 // If true, this is an explicit interface implementation
3305 public readonly bool IsExplicitImpl;
3307 protected bool is_external_implementation;
3310 // The interface type we are explicitly implementing
3312 public TypeSpec InterfaceType;
3315 // The method we're overriding if this is an override method.
3317 protected MethodSpec base_method;
3319 readonly Modifiers explicit_mod_flags;
3320 public MethodAttributes flags;
3322 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3323 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3325 IsInterface = parent.Kind == MemberKind.Interface;
3326 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3327 explicit_mod_flags = mod;
3330 public abstract Variance ExpectedMemberTypeVariance { get; }
3332 protected override bool CheckBase ()
3334 if (!base.CheckBase ())
3337 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3338 CheckForDuplications ();
3343 // For System.Object only
3344 if (Parent.BaseType == null)
3347 MemberSpec candidate;
3348 bool overrides = false;
3349 var base_member = FindBaseMember (out candidate, ref overrides);
3351 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3352 if (base_member == null) {
3353 if (candidate == null) {
3354 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3355 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3356 "object.Finalize()");
3358 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3359 GetSignatureForError (), SimpleName.GetMemberType (this));
3362 Report.SymbolRelatedToPreviousError (candidate);
3364 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3365 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3366 else if (this is PropertyBase)
3367 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3368 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3370 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3371 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3378 // Handles ambiguous overrides
3380 if (candidate != null) {
3381 Report.SymbolRelatedToPreviousError (candidate);
3382 Report.SymbolRelatedToPreviousError (base_member);
3384 // Get member definition for error reporting
3385 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3386 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3388 Report.Error (462, Location,
3389 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3390 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3393 if (!CheckOverrideAgainstBase (base_member))
3396 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3398 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3399 Report.SymbolRelatedToPreviousError (base_member);
3400 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3401 GetSignatureForError (), base_member.GetSignatureForError ());
3404 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3405 Report.SymbolRelatedToPreviousError (base_member);
3406 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3407 GetSignatureForError (), base_member.GetSignatureForError ());
3411 base_method = base_member as MethodSpec;
3415 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3416 base_member = candidate;
3418 if (base_member == null) {
3419 if ((ModFlags & Modifiers.NEW) != 0) {
3420 if (base_member == null) {
3421 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3422 GetSignatureForError ());
3426 if ((ModFlags & Modifiers.NEW) == 0) {
3427 ModFlags |= Modifiers.NEW;
3428 if (!IsCompilerGenerated) {
3429 Report.SymbolRelatedToPreviousError (base_member);
3430 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3431 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",
3432 GetSignatureForError (), base_member.GetSignatureForError ());
3434 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3435 GetSignatureForError (), base_member.GetSignatureForError ());
3440 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3441 switch (base_member.Kind) {
3442 case MemberKind.Event:
3443 case MemberKind.Indexer:
3444 case MemberKind.Method:
3445 case MemberKind.Property:
3446 Report.SymbolRelatedToPreviousError (base_member);
3447 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3448 GetSignatureForError (), base_member.GetSignatureForError ());
3457 protected virtual bool CheckForDuplications ()
3459 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3463 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3464 // that have been defined.
3466 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3470 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3471 Report.SymbolRelatedToPreviousError (base_member);
3472 Report.Error (506, Location,
3473 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3474 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3478 // Now we check that the overriden method is not final
3479 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3480 Report.SymbolRelatedToPreviousError (base_member);
3481 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3482 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3486 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3487 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3488 Report.SymbolRelatedToPreviousError (base_member);
3489 if (this is PropertyBasedMember) {
3490 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3491 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3493 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3494 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3502 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3504 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3505 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3507 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3509 // It must be at least "protected"
3511 if ((thisp & Modifiers.PROTECTED) == 0) {
3516 // when overriding protected internal, the method can be declared
3517 // protected internal only within the same assembly or assembly
3518 // which has InternalsVisibleTo
3520 if ((thisp & Modifiers.INTERNAL) != 0) {
3521 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3525 // protected overriding protected internal inside same assembly
3526 // requires internal modifier as well
3528 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3535 return thisp == base_classp;
3538 public override bool Define ()
3541 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3542 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3544 flags = MethodAttributes.Public |
3545 MethodAttributes.Abstract |
3546 MethodAttributes.HideBySig |
3547 MethodAttributes.NewSlot |
3548 MethodAttributes.Virtual;
3550 Parent.PartialContainer.MethodModifiersValid (this);
3552 flags = ModifiersExtensions.MethodAttr (ModFlags);
3555 if (IsExplicitImpl) {
3556 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3557 if (InterfaceType == null)
3560 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3561 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3562 GetSignatureForError ());
3565 if (!InterfaceType.IsInterface) {
3566 Report.SymbolRelatedToPreviousError (InterfaceType);
3567 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3568 InterfaceType.GetSignatureForError ());
3570 Parent.PartialContainer.VerifyImplements (this);
3573 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3575 allowed_explicit |= Modifiers.ASYNC;
3577 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3580 return base.Define ();
3583 protected bool DefineParameters (ParametersCompiled parameters)
3585 if (!parameters.Resolve (this))
3589 for (int i = 0; i < parameters.Count; ++i) {
3590 Parameter p = parameters [i];
3592 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3593 p.Warning_UselessOptionalParameter (Report);
3595 if (p.CheckAccessibility (this))
3598 TypeSpec t = parameters.Types [i];
3599 Report.SymbolRelatedToPreviousError (t);
3600 if (this is Indexer)
3601 Report.Error (55, Location,
3602 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3603 t.GetSignatureForError (), GetSignatureForError ());
3604 else if (this is Operator)
3605 Report.Error (57, Location,
3606 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3607 t.GetSignatureForError (), GetSignatureForError ());
3609 Report.Error (51, Location,
3610 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3611 t.GetSignatureForError (), GetSignatureForError ());
3617 protected override void DoMemberTypeDependentChecks ()
3619 base.DoMemberTypeDependentChecks ();
3621 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3624 public override void Emit()
3626 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3627 // We are more strict than csc and report this as an error because SRE does not allow emit that
3628 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3629 if (this is Constructor) {
3630 Report.Warning (824, 1, Location,
3631 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3633 Report.Warning (626, 1, Location,
3634 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3635 GetSignatureForError ());
3642 public override bool EnableOverloadChecks (MemberCore overload)
3645 // Two members can differ in their explicit interface
3646 // type parameter only
3648 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3649 if (imb != null && imb.IsExplicitImpl) {
3650 if (IsExplicitImpl) {
3651 caching_flags |= Flags.MethodOverloadsExist;
3656 return IsExplicitImpl;
3659 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3661 var base_modifiers = base_member.Modifiers;
3663 // Remove internal modifier from types which are not internally accessible
3664 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3665 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3666 base_modifiers = Modifiers.PROTECTED;
3668 Report.SymbolRelatedToPreviousError (base_member);
3669 Report.Error (507, member.Location,
3670 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3671 member.GetSignatureForError (),
3672 ModifiersExtensions.AccessibilityName (base_modifiers),
3673 base_member.GetSignatureForError ());
3676 protected void Error_StaticReturnType ()
3678 Report.Error (722, Location,
3679 "`{0}': static types cannot be used as return types",
3680 MemberType.GetSignatureForError ());
3684 /// Gets base method and its return type
3686 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3688 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3692 // The "short" name of this property / indexer / event. This is the
3693 // name without the explicit interface.
3695 public string ShortName {
3696 get { return MemberName.Name; }
3700 // Returns full metadata method name
3702 public string GetFullName (MemberName name)
3704 return GetFullName (name.Name);
3707 public string GetFullName (string name)
3709 if (!IsExplicitImpl)
3713 // When dealing with explicit members a full interface type
3714 // name is added to member name to avoid possible name conflicts
3716 // We use CSharpName which gets us full name with benefit of
3717 // replacing predefined names which saves some space and name
3720 return InterfaceType.GetSignatureForError () + "." + name;
3723 public override string GetSignatureForDocumentation ()
3726 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3728 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3731 public override bool IsUsed
3733 get { return IsExplicitImpl || base.IsUsed; }
3736 public override void SetConstraints (List<Constraints> constraints_list)
3738 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3739 Report.Error (460, Location,
3740 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3741 GetSignatureForError ());
3744 base.SetConstraints (constraints_list);
3748 public abstract class MemberBase : MemberCore
3750 protected FullNamedExpression type_expr;
3751 protected TypeSpec member_type;
3752 public new TypeDefinition Parent;
3754 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3755 : base (parent, name, attrs)
3757 this.Parent = parent;
3758 this.type_expr = type;
3760 if (name != MemberName.Null)
3761 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3766 public TypeSpec MemberType {
3772 public FullNamedExpression TypeExpression {
3781 // Main member define entry
3783 public override bool Define ()
3785 DoMemberTypeIndependentChecks ();
3788 // Returns false only when type resolution failed
3790 if (!ResolveMemberType ())
3793 DoMemberTypeDependentChecks ();
3798 // Any type_name independent checks
3800 protected virtual void DoMemberTypeIndependentChecks ()
3802 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3803 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3804 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3805 GetSignatureForError (), Parent.GetSignatureForError ());
3810 // Any type_name dependent checks
3812 protected virtual void DoMemberTypeDependentChecks ()
3814 // verify accessibility
3815 if (!IsAccessibleAs (MemberType)) {
3816 Report.SymbolRelatedToPreviousError (MemberType);
3817 if (this is Property)
3818 Report.Error (53, Location,
3819 "Inconsistent accessibility: property type `" +
3820 MemberType.GetSignatureForError () + "' is less " +
3821 "accessible than property `" + GetSignatureForError () + "'");
3822 else if (this is Indexer)
3823 Report.Error (54, Location,
3824 "Inconsistent accessibility: indexer return type `" +
3825 MemberType.GetSignatureForError () + "' is less " +
3826 "accessible than indexer `" + GetSignatureForError () + "'");
3827 else if (this is MethodCore) {
3828 if (this is Operator)
3829 Report.Error (56, Location,
3830 "Inconsistent accessibility: return type `" +
3831 MemberType.GetSignatureForError () + "' is less " +
3832 "accessible than operator `" + GetSignatureForError () + "'");
3834 Report.Error (50, Location,
3835 "Inconsistent accessibility: return type `" +
3836 MemberType.GetSignatureForError () + "' is less " +
3837 "accessible than method `" + GetSignatureForError () + "'");
3838 } else if (this is Event) {
3839 Report.Error (7025, Location,
3840 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3841 MemberType.GetSignatureForError (), GetSignatureForError ());
3843 Report.Error (52, Location,
3844 "Inconsistent accessibility: field type `" +
3845 MemberType.GetSignatureForError () + "' is less " +
3846 "accessible than field `" + GetSignatureForError () + "'");
3851 protected void IsTypePermitted ()
3853 if (MemberType.IsSpecialRuntimeType) {
3854 if (Parent is StateMachine) {
3855 Report.Error (4012, Location,
3856 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3857 MemberType.GetSignatureForError ());
3858 } else if (Parent is HoistedStoreyClass) {
3859 Report.Error (4013, Location,
3860 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3861 MemberType.GetSignatureForError ());
3863 Report.Error (610, Location,
3864 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3869 protected virtual bool CheckBase ()
3871 CheckProtectedModifier ();
3876 public override string GetSignatureForDocumentation ()
3878 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3881 protected virtual bool ResolveMemberType ()
3883 if (member_type != null)
3884 throw new InternalErrorException ("Multi-resolve");
3886 member_type = type_expr.ResolveAsType (this);
3887 return member_type != null;