//
// Copyright 2001 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2010 Novell, Inc
+// Copyright 2011 Xamarin Inc
//
//
InternalCompilerType = 1 << 21,
MissingType = 1 << 22,
Void = 1 << 23,
+ Namespace = 1 << 24,
NestedMask = Class | Struct | Delegate | Enum | Interface,
GenericMask = Method | Class | Struct | Delegate | Interface,
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;
// contain all base interface members, so the Lookup code
// can use simple inheritance rules.
//
+ // Does not work recursively because of generic interfaces
+ //
public void AddInterface (TypeSpec iface)
{
var cache = iface.MemberCache;
}
foreach (var ce in entry.Value) {
+ //
+ // When two or more different base interfaces implemenent common
+ // interface
+ //
+ // I : IA, IFoo
+ // IA : IFoo
+ //
if (list.Contains (ce))
continue;
member_hash[entry.Key] = list;
}
}
-
- // Add also all base interfaces
- if (iface.Interfaces != null) {
- foreach (var base_iface in iface.Interfaces)
- AddInterface (base_iface);
- }
}
public void AddMember (InterfaceMemberBase imb, string exlicitName, MemberSpec ms)
{
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;
+ }
}
}
// 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<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnly)
+ // declaredOnlyClass cannot be used interfaces. Manual filtering is required because names are
+ // compacted
+ //
+ public static IList<MemberSpec> FindMembers (TypeSpec container, string name, bool declaredOnlyClass)
{
IList<MemberSpec> 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;
// 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--) {
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)
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;
return IndexerNameAlias;
if (mc is Constructor)
- return Constructor.ConstructorName;
+ return mc.IsStatic ? Constructor.TypeConstructorName : Constructor.ConstructorName;
return mc.MemberName.Name;
}
public static IList<MemberSpec> GetUserOperator (TypeSpec container, Operator.OpType op, bool declaredOnly)
{
IList<MemberSpec> found = null;
-
+ bool shared_list = true;
IList<MemberSpec> applicable;
do {
var mc = container.MemberCache;
found = new List<MemberSpec> ();
found.Add (applicable[i]);
} else {
- var prev = found as List<MemberSpec>;
- if (prev == null) {
+ List<MemberSpec> prev;
+ if (shared_list) {
+ shared_list = false;
prev = new List<MemberSpec> (found.Count + 1);
prev.AddRange (found);
+ } else {
+ prev = (List<MemberSpec>) found;
}
prev.Add (applicable[i]);
} else {
if (found == null) {
found = applicable;
+ shared_list = true;
} else {
- var merged = found as List<MemberSpec>;
- if (merged == null) {
+ List<MemberSpec> merged;
+ if (shared_list) {
+ shared_list = false;
merged = new List<MemberSpec> (found.Count + applicable.Count);
merged.AddRange (found);
found = merged;
+ } else {
+ merged = (List<MemberSpec>) found;
}
merged.AddRange (applicable);
if (container.BaseType == null) {
locase_members = new Dictionary<string, MemberSpec[]> (member_hash.Count); // StringComparer.OrdinalIgnoreCase);
} else {
- container.BaseType.MemberCache.VerifyClsCompliance (container.BaseType, report);
- locase_members = new Dictionary<string, MemberSpec[]> (container.BaseType.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase);
+ var btype = container.BaseType.GetDefinition ();
+ btype.MemberCache.VerifyClsCompliance (btype, report);
+ locase_members = new Dictionary<string, MemberSpec[]> (btype.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase);
}
var is_imported_type = container.MemberDefinition.IsImported;
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;
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);
}
}
}
} 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 (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);
+ }
+ }
-// if (f.IsAccessor && name_entry.IsAccessor)
-// continue;
+ continue;
+ }
same_names_only = false;
if (!is_imported_type) {
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);
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);
//
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) {
"A partial method declaration and partial method implementation must be both `static' or neither");
}
- Report.SymbolRelatedToPreviousError (ce);
- Report.Error (764, member.Location,
- "A partial method declaration and partial method implementation must be both `unsafe' or neither");
+ if ((method_a.ModFlags & Modifiers.UNSAFE) != (method_b.ModFlags & Modifiers.UNSAFE)) {
+ Report.SymbolRelatedToPreviousError (ce);
+ Report.Error (764, member.Location,
+ "A partial method declaration and partial method implementation must be both `unsafe' or neither");
+ }
+
return false;
}