X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fmembercache.cs;h=c2d9a630a3aa1324bb790cd19fe42e7ebef21d60;hb=f3edca943070399b06d33f3ba3e99c76a9d9886d;hp=dc9a32dee3624197c8ff0a377207a9503da59e60;hpb=9e0dbd3d16792ddaf2e882c454e12296ad6c1847;p=mono.git diff --git a/mcs/mcs/membercache.cs b/mcs/mcs/membercache.cs index dc9a32dee36..c2d9a630a3a 100644 --- a/mcs/mcs/membercache.cs +++ b/mcs/mcs/membercache.cs @@ -8,6 +8,7 @@ // // Copyright 2001 Ximian, Inc (http://www.ximian.com) // Copyright 2004-2010 Novell, Inc +// Copyright 2011 Xamarin Inc // // @@ -40,6 +41,7 @@ namespace Mono.CSharp { InternalCompilerType = 1 << 21, MissingType = 1 << 22, Void = 1 << 23, + Namespace = 1 << 24, NestedMask = Class | Struct | Delegate | Enum | Interface, GenericMask = Method | Class | Struct | Delegate | Interface, @@ -71,15 +73,6 @@ namespace Mono.CSharp { public readonly TypeSpec MemberType; public readonly int Arity; // -1 to ignore the check - private MemberFilter (string name, MemberKind kind) - { - Name = name; - Kind = kind; - Parameters = null; - MemberType = null; - Arity = -1; - } - public MemberFilter (MethodSpec m) { Name = m.Name; @@ -302,24 +295,28 @@ namespace Mono.CSharp { { if (member.Kind == MemberKind.Operator) { var dt = member.DeclaringType; - switch (dt.BuiltinType) { - case BuiltinTypeSpec.Type.String: - case BuiltinTypeSpec.Type.Delegate: - case BuiltinTypeSpec.Type.MulticastDelegate: - // Some core types have user operators but they cannot be used as normal - // user operators as they are predefined and therefore having different - // rules (e.g. binary operators) by not setting the flag we hide them for - // user conversions - // TODO: Should I do this for all core types ? - break; - default: - if (name == Operator.GetMetadataName (Operator.OpType.Implicit) || name == Operator.GetMetadataName (Operator.OpType.Explicit)) { - state |= StateFlags.HasConversionOperator; - } else { - state |= StateFlags.HasUserOperator; - } - break; + // + // Some core types have user operators but they cannot be used like normal + // user operators as they are predefined and therefore having different + // rules (e.g. binary operators) by not setting the flag we hide them for + // user conversions + // + if (!BuiltinTypeSpec.IsPrimitiveType (dt) || dt.BuiltinType == BuiltinTypeSpec.Type.Char) { + switch (dt.BuiltinType) { + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + break; + default: + if (name == Operator.GetMetadataName (Operator.OpType.Implicit) || name == Operator.GetMetadataName (Operator.OpType.Explicit)) { + state |= StateFlags.HasConversionOperator; + } else { + state |= StateFlags.HasUserOperator; + } + + break; + } } } @@ -438,12 +435,15 @@ namespace Mono.CSharp { // A special method to work with member lookup only. It returns a list of all members named @name // starting from @container. It's very performance sensitive // - public static IList FindMembers (TypeSpec container, string name, bool declaredOnly) + // declaredOnlyClass cannot be used interfaces. Manual filtering is required because names are + // compacted + // + public static IList FindMembers (TypeSpec container, string name, bool declaredOnlyClass) { IList applicable; do { - if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnly) + if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnlyClass) return applicable; container = container.BaseType; @@ -467,7 +467,7 @@ namespace Mono.CSharp { // based on type definition var tc = container.MemberDefinition as TypeContainer; if (tc != null) - tc.DefineType (); + tc.DefineContainer (); if (container.MemberCacheTypes.member_hash.TryGetValue (name, out applicable)) { for (int i = applicable.Count - 1; i >= 0; i--) { @@ -684,6 +684,44 @@ namespace Mono.CSharp { throw new NotImplementedException (member.GetType ().ToString ()); } + public static List GetAllFieldsForDefiniteAssignment (TypeSpec container) + { + List fields = null; + foreach (var entry in container.MemberCache.member_hash) { + foreach (var name_entry in entry.Value) { + if (name_entry.Kind != MemberKind.Field) + continue; + + if ((name_entry.Modifiers & Modifiers.STATIC) != 0) + continue; + + // + // Fixed size buffers are not subject to definite assignment checking + // + if (name_entry is FixedFieldSpec || name_entry is ConstSpec) + continue; + + var fs = (FieldSpec) name_entry; + + // + // LAMESPEC: Very bizzare hack, definitive assignment is not done + // for imported non-public reference fields except array. No idea what the + // actual csc rule is + // + if (!fs.IsPublic && container.MemberDefinition.IsImported && (!fs.MemberType.IsArray && TypeSpec.IsReferenceType (fs.MemberType))) + continue; + + if (fields == null) + fields = new List (); + + fields.Add (fs); + break; + } + } + + return fields ?? new List (0); + } + public static IList GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name) { var matches = new List (); @@ -710,7 +748,7 @@ namespace Mono.CSharp { // // Returns members of @iface only, base members are ignored // - public static IList GetInterfaceMethods (TypeSpec iface) + public static List GetInterfaceMethods (TypeSpec iface) { // // MemberCache flatten interfaces, therefore in cases like this one @@ -753,7 +791,7 @@ namespace Mono.CSharp { while (true) { foreach (var entry in abstract_type.MemberCache.member_hash) { foreach (var name_entry in entry.Value) { - if ((name_entry.Modifiers & Modifiers.ABSTRACT) == 0) + if ((name_entry.Modifiers & (Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != Modifiers.ABSTRACT) continue; if (name_entry.Kind != MemberKind.Method) @@ -802,6 +840,12 @@ namespace Mono.CSharp { if ((item.Modifiers & (Modifiers.OVERRIDE | Modifiers.VIRTUAL)) == 0) continue; + // + // Abstract override does not override anything + // + if ((item.Modifiers & Modifiers.ABSTRACT) != 0) + continue; + if (filter.Equals (item)) { --not_implemented_count; abstract_methods [i] = null; @@ -850,7 +894,7 @@ namespace Mono.CSharp { return IndexerNameAlias; if (mc is Constructor) - return Constructor.ConstructorName; + return mc.IsStatic ? Constructor.TypeConstructorName : Constructor.ConstructorName; return mc.MemberName.Name; } @@ -1119,8 +1163,9 @@ namespace Mono.CSharp { if (container.BaseType == null) { locase_members = new Dictionary (member_hash.Count); // StringComparer.OrdinalIgnoreCase); } else { - container.BaseType.MemberCache.VerifyClsCompliance (container.BaseType, report); - locase_members = new Dictionary (container.BaseType.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase); + var btype = container.BaseType.GetDefinition (); + btype.MemberCache.VerifyClsCompliance (btype, report); + locase_members = new Dictionary (btype.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase); } var is_imported_type = container.MemberDefinition.IsImported; @@ -1139,10 +1184,14 @@ namespace Mono.CSharp { if (name_entry.MemberDefinition.CLSAttributeValue == false) continue; - IParametersMember p_a = name_entry as IParametersMember; - if (p_a != null && !name_entry.IsAccessor) { - if (!is_imported_type) { + IParametersMember p_a = null; + if (!is_imported_type) { + p_a = name_entry as IParametersMember; + if (p_a != null && !name_entry.IsAccessor) { var p_a_pd = p_a.Parameters; + // + // Check differing overloads in @container + // for (int ii = i + 1; ii < entry.Value.Count; ++ii) { var checked_entry = entry.Value[ii]; IParametersMember p_b = checked_entry as IParametersMember; @@ -1157,24 +1206,7 @@ namespace Mono.CSharp { var res = ParametersCompiled.IsSameClsSignature (p_a.Parameters, p_b.Parameters); if (res != 0) { - var last = GetLaterDefinedMember (checked_entry, name_entry); - if (last == checked_entry.MemberDefinition) { - report.SymbolRelatedToPreviousError (name_entry); - } else { - report.SymbolRelatedToPreviousError (checked_entry); - } - - if ((res & 1) != 0) { - report.Warning (3006, 1, last.Location, - "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", - name_entry.GetSignatureForError ()); - } - - if ((res & 2) != 0) { - report.Warning (3007, 1, last.Location, - "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", - name_entry.GetSignatureForError ()); - } + ReportOverloadedMethodClsDifference (name_entry, checked_entry, res, report); } } } @@ -1192,11 +1224,26 @@ namespace Mono.CSharp { } else { bool same_names_only = true; foreach (var f in found) { - if (f.Name == name_entry.Name) - continue; + if (f.Name == name_entry.Name) { + if (p_a != null) { + IParametersMember p_b = f as IParametersMember; + if (p_b == null) + continue; -// if (f.IsAccessor && name_entry.IsAccessor) -// continue; + if (p_a.Parameters.Count != p_b.Parameters.Count) + continue; + + if (f.IsAccessor) + continue; + + var res = ParametersCompiled.IsSameClsSignature (p_a.Parameters, p_b.Parameters); + if (res != 0) { + ReportOverloadedMethodClsDifference (f, name_entry, res, report); + } + } + + continue; + } same_names_only = false; if (!is_imported_type) { @@ -1235,12 +1282,37 @@ namespace Mono.CSharp { if (mc_b == null) return mc_a; + if (a.DeclaringType.MemberDefinition != b.DeclaringType.MemberDefinition) + return mc_b; + if (mc_a.Location.File != mc_a.Location.File) return mc_b; return mc_b.Location.Row > mc_a.Location.Row ? mc_b : mc_a; } + static void ReportOverloadedMethodClsDifference (MemberSpec a, MemberSpec b, int res, Report report) + { + var last = GetLaterDefinedMember (a, b); + if (last == a.MemberDefinition) { + report.SymbolRelatedToPreviousError (b); + } else { + report.SymbolRelatedToPreviousError (a); + } + + if ((res & 1) != 0) { + report.Warning (3006, 1, last.Location, + "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", + last.GetSignatureForError ()); + } + + if ((res & 2) != 0) { + report.Warning (3007, 1, last.Location, + "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", + last.GetSignatureForError ()); + } + } + public bool CheckExistingMembersOverloads (MemberCore member, AParametersCollection parameters) { var name = GetLookupName (member); @@ -1283,8 +1355,10 @@ namespace Mono.CSharp { type_a = parameters.Types [ii]; type_b = p_types [ii]; - if ((pd.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF) != - (parameters.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF)) + var a_byref = (pd.FixedParameters[ii].ModFlags & Parameter.Modifier.RefOutMask) != 0; + var b_byref = (parameters.FixedParameters[ii].ModFlags & Parameter.Modifier.RefOutMask) != 0; + + if (a_byref != b_byref) break; } while (TypeSpecComparer.Override.IsEqual (type_a, type_b) && ii-- != 0); @@ -1303,7 +1377,9 @@ namespace Mono.CSharp { // if (pd != null && member is MethodCore) { ii = method_param_count; - while (ii-- != 0 && parameters.FixedParameters[ii].ModFlags == pd.FixedParameters[ii].ModFlags && + while (ii-- != 0 && + (parameters.FixedParameters[ii].ModFlags & Parameter.Modifier.ModifierMask) == + (pd.FixedParameters[ii].ModFlags & Parameter.Modifier.ModifierMask) && parameters.ExtensionMethodType == pd.ExtensionMethodType) ; if (ii >= 0) {