X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdecl.cs;h=6b341f0de709f57eaea7ab56f55ae425ca5b0d56;hb=24b2c4de33c81f823f3da28ccf5a8e12f560820d;hp=d93df4cadc443e24b18850bdc25e81971eb651be;hpb=36f0ac057ef56a10171ef342decab68a6f9d81a5;p=mono.git diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs index d93df4cadc4..6b341f0de70 100644 --- a/mcs/mcs/decl.cs +++ b/mcs/mcs/decl.cs @@ -4,12 +4,11 @@ // Author: Miguel de Icaza (miguel@gnu.org) // Marek Safar (marek.safar@seznam.cz) // -// Licensed under the terms of the GNU GPL +// Dual licensed under the terms of the MIT X11 or GNU GPL // -// (C) 2001 Ximian, Inc (http://www.ximian.com) -// (C) 2004 Novell, Inc +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc // -// TODO: Move the method verification stuff from the class.cs and interface.cs here // using System; @@ -27,6 +26,9 @@ using System.Xml; namespace Mono.CSharp { + // + // Better name would be DottenName + // public class MemberName { public readonly string Name; public readonly TypeArguments TypeArguments; @@ -95,6 +97,7 @@ namespace Mono.CSharp { this.Left = (right.Left == null) ? left : new MemberName (left, right.Left); } + // TODO: Remove public string GetName () { return GetName (false); @@ -114,23 +117,13 @@ namespace Mono.CSharp { public string GetName (bool is_generic) { string name = is_generic ? Basename : Name; - string connect = is_double_colon ? "::" : "."; if (Left != null) - return Left.GetName (is_generic) + connect + name; - else - return name; - } + return Left.GetName (is_generic) + (is_double_colon ? "::" : ".") + name; - public string GetTypeName () - { - string connect = is_double_colon ? "::" : "."; - if (Left != null) - return Left.GetTypeName () + connect + MakeName (Name, TypeArguments); - else - return MakeName (Name, TypeArguments); + return name; } - public Expression GetTypeExpression () + public ATypeNameExpression GetTypeExpression () { if (Left == null) { if (TypeArguments != null) @@ -142,7 +135,7 @@ namespace Mono.CSharp { if (is_double_colon) { if (Left.Left != null) throw new InternalErrorException ("The left side of a :: should be an identifier"); - return new QualifiedAliasMember (Left.Name, Basename, Location); + return new QualifiedAliasMember (Left.Name, Name, TypeArguments, Location); } Expression lexpr = Left.GetTypeExpression (); @@ -159,36 +152,17 @@ namespace Mono.CSharp { get { if (TypeArguments != null) return MakeName (Name, TypeArguments); - else - return Name; - } - } - - public string FullName { - get { - if (TypeArguments != null) - return Name + "<" + TypeArguments + ">"; - else - return Name; + return Name; } } - public string MethodName { - get { - string connect = is_double_colon ? "::" : "."; - if (Left != null) - return Left.FullName + connect + Name; - else - return Name; - } - } - public string GetSignatureForError () { - if (TypeArguments != null) - return MethodName + "<" + TypeArguments.GetSignatureForError () + ">"; - - return MethodName; + string append = TypeArguments == null ? "" : "<" + TypeArguments.GetSignatureForError () + ">"; + if (Left == null) + return Name + append; + string connect = is_double_colon ? "::" : "."; + return Left.GetSignatureForError () + connect + Name + append; } public override bool Equals (object other) @@ -247,8 +221,8 @@ namespace Mono.CSharp { { if (args == null) return name; - else - return name + "`" + args.Count; + + return name + "`" + args.Count; } public static string MakeName (string name, int count) @@ -267,6 +241,7 @@ namespace Mono.CSharp { /// protected string cached_name; + // TODO: Remove in favor of MemberName public string Name { get { if (cached_name == null) @@ -332,7 +307,8 @@ namespace Mono.CSharp { IsUsed = 1 << 11, IsAssigned = 1 << 12, // Field is assigned HasExplicitLayout = 1 << 13, - PartialDefinitionExists = 1 << 14 // Set when corresponding partial method definition exists + PartialDefinitionExists = 1 << 14, // Set when corresponding partial method definition exists + HasStructLayout = 1 << 15 // Has StructLayoutAttribute } /// @@ -353,7 +329,7 @@ namespace Mono.CSharp { member_name = new_name; cached_name = null; } - + protected bool CheckAbstractAndExtern (bool has_block) { if (Parent.PartialContainer.Kind == Kind.Interface) @@ -373,19 +349,52 @@ namespace Mono.CSharp { } } else { if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0) { - if (RootContext.Version >= LanguageVersion.LINQ && this is Property.PropertyMethod) { - Report.Error (840, Location, "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors", - GetSignatureForError ()); - } else { - Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial", - GetSignatureForError ()); + if (RootContext.Version >= LanguageVersion.V_3) { + Property.PropertyMethod pm = this as Property.PropertyMethod; + if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod) + pm = null; + + if (pm != null && (pm.Property.Get.IsDummy || pm.Property.Set.IsDummy)) { + Report.Error (840, Location, + "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors", + GetSignatureForError ()); + return false; + } } + + Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial", + GetSignatureForError ()); return false; } } return true; - } + } + + public void CheckProtectedModifier () + { + if ((ModFlags & Modifiers.PROTECTED) == 0) + return; + + if (Parent.PartialContainer.Kind == Kind.Struct) { + Report.Error (666, Location, "`{0}': Structs cannot contain protected members", + GetSignatureForError ()); + return; + } + + if ((Parent.ModFlags & Modifiers.STATIC) != 0) { + Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members", + GetSignatureForError ()); + return; + } + + if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 && + !(this is Destructor)) { + Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", + GetSignatureForError ()); + return; + } + } public abstract bool Define (); @@ -417,7 +426,17 @@ namespace Mono.CSharp { if (!RootContext.VerifyClsCompliance) return; - VerifyClsCompliance (); + if (Report.WarningLevel > 0) + VerifyClsCompliance (); + } + + public bool IsCompilerGenerated { + get { + if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0) + return true; + + return Parent == null ? false : Parent.IsCompilerGenerated; + } } public virtual bool IsUsed { @@ -434,26 +453,24 @@ namespace Mono.CSharp { /// public virtual ObsoleteAttribute GetObsoleteAttribute () { - // ((flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) is slower, but why ? - if ((caching_flags & Flags.Obsolete_Undetected) == 0 && (caching_flags & Flags.Obsolete) == 0) { + if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) return null; - } caching_flags &= ~Flags.Obsolete_Undetected; if (OptAttributes == null) return null; - Attribute obsolete_attr = OptAttributes.Search ( - TypeManager.obsolete_attribute_type); + Attribute obsolete_attr = OptAttributes.Search (PredefinedAttributes.Get.Obsolete); if (obsolete_attr == null) return null; + caching_flags |= Flags.Obsolete; + ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (); if (obsolete == null) return null; - caching_flags |= Flags.Obsolete; return obsolete; } @@ -462,15 +479,160 @@ namespace Mono.CSharp { /// public virtual void CheckObsoleteness (Location loc) { - if (Parent != null) - Parent.CheckObsoleteness (loc); - ObsoleteAttribute oa = GetObsoleteAttribute (); - if (oa == null) { - return; + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); + } + + // Access level of a type. + const int X = 1; + enum AccessLevel + { // Each column represents `is this scope larger or equal to Blah scope' + // Public Assembly Protected + Protected = (0 << 0) | (0 << 1) | (X << 2), + Public = (X << 0) | (X << 1) | (X << 2), + Private = (0 << 0) | (0 << 1) | (0 << 2), + Internal = (0 << 0) | (X << 1) | (0 << 2), + ProtectedOrInternal = (0 << 0) | (X << 1) | (X << 2), + } + + static AccessLevel GetAccessLevelFromModifiers (int flags) + { + if ((flags & Modifiers.INTERNAL) != 0) { + + if ((flags & Modifiers.PROTECTED) != 0) + return AccessLevel.ProtectedOrInternal; + else + return AccessLevel.Internal; + + } else if ((flags & Modifiers.PROTECTED) != 0) + return AccessLevel.Protected; + else if ((flags & Modifiers.PRIVATE) != 0) + return AccessLevel.Private; + else + return AccessLevel.Public; + } + + // + // Returns the access level for type `t' + // + static AccessLevel GetAccessLevelFromType (Type t) + { + if (t.IsPublic) + return AccessLevel.Public; + if (t.IsNestedPrivate) + return AccessLevel.Private; + if (t.IsNotPublic) + return AccessLevel.Internal; + + if (t.IsNestedPublic) + return AccessLevel.Public; + if (t.IsNestedAssembly) + return AccessLevel.Internal; + if (t.IsNestedFamily) + return AccessLevel.Protected; + if (t.IsNestedFamORAssem) + return AccessLevel.ProtectedOrInternal; + if (t.IsNestedFamANDAssem) + throw new NotImplementedException ("NestedFamANDAssem not implemented, cant make this kind of type from c# anyways"); + + // nested private is taken care of + + throw new Exception ("I give up, what are you?"); + } + + // + // Checks whether the type P is as accessible as this member + // + public bool IsAccessibleAs (Type p) + { + // + // if M is private, its accessibility is the same as this declspace. + // we already know that P is accessible to T before this method, so we + // may return true. + // + if ((mod_flags & Modifiers.PRIVATE) != 0) + return true; + + while (TypeManager.HasElementType (p)) + p = TypeManager.GetElementType (p); + + if (TypeManager.IsGenericParameter (p)) + return true; + + if (TypeManager.IsGenericType (p)) { + foreach (Type t in TypeManager.GetTypeArguments (p)) { + if (!IsAccessibleAs (t)) + return false; + } + } + + for (Type p_parent = null; p != null; p = p_parent) { + p_parent = p.DeclaringType; + AccessLevel pAccess = GetAccessLevelFromType (p); + if (pAccess == AccessLevel.Public) + continue; + + bool same_access_restrictions = false; + for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) { + AccessLevel al = GetAccessLevelFromModifiers (mc.ModFlags); + switch (pAccess) { + case AccessLevel.Internal: + if (al == AccessLevel.Private || al == AccessLevel.Internal) + same_access_restrictions = TypeManager.IsThisOrFriendAssembly (p.Assembly); + + break; + + case AccessLevel.Protected: + if (al == AccessLevel.Protected) { + same_access_restrictions = mc.Parent.IsBaseType (p_parent); + break; + } + + if (al == AccessLevel.Private) { + // + // When type is private and any of its parents derives from + // protected type then the type is accessible + // + while (mc.Parent != null) { + if (mc.Parent.IsBaseType (p_parent)) + same_access_restrictions = true; + mc = mc.Parent; + } + } + + break; + + case AccessLevel.ProtectedOrInternal: + if (al == AccessLevel.Protected) + same_access_restrictions = mc.Parent.IsBaseType (p_parent); + else if (al == AccessLevel.Internal) + same_access_restrictions = TypeManager.IsThisOrFriendAssembly (p.Assembly); + else if (al == AccessLevel.ProtectedOrInternal) + same_access_restrictions = mc.Parent.IsBaseType (p_parent) && + TypeManager.IsThisOrFriendAssembly (p.Assembly); + + break; + + case AccessLevel.Private: + // + // Both are private and share same parent + // + if (al == AccessLevel.Private) + same_access_restrictions = TypeManager.IsEqual (mc.Parent.TypeBuilder, p_parent); + + break; + + default: + throw new InternalErrorException (al.ToString ()); + } + } + + if (!same_access_restrictions) + return false; } - AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); + return true; } /// @@ -521,7 +683,7 @@ namespace Mono.CSharp { if (OptAttributes != null) { Attribute cls_attribute = OptAttributes.Search ( - TypeManager.cls_compliant_attribute_type); + PredefinedAttributes.Get.CLSCompliant); if (cls_attribute != null) { caching_flags |= Flags.HasClsCompliantAttribute; bool value = cls_attribute.GetClsCompliantAttributeValue (); @@ -572,31 +734,38 @@ namespace Mono.CSharp { { if (!IsClsComplianceRequired ()) { if (HasClsCompliantAttribute && Report.WarningLevel >= 2) { - if (!IsExposedFromAssembly ()) - Report.Warning (3019, 2, Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ()); - if (!CodeGen.Assembly.IsClsCompliant) - Report.Warning (3021, 2, Location, "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", GetSignatureForError ()); + if (!IsExposedFromAssembly ()) { + Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant); + Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ()); + } + + if (!CodeGen.Assembly.IsClsCompliant) { + Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant); + Report.Warning (3021, 2, a.Location, "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", GetSignatureForError ()); + } } return false; } if (HasClsCompliantAttribute) { if (CodeGen.Assembly.ClsCompliantAttribute == null && !CodeGen.Assembly.IsClsCompliant) { - Report.Error (3014, Location, + Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant); + Report.Warning (3014, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant", GetSignatureForError ()); return false; } if (!Parent.IsClsComplianceRequired ()) { - Report.Warning (3018, 1, Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", + Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CLSCompliant); + Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", GetSignatureForError (), Parent.GetSignatureForError ()); return false; } } if (member_name.Name [0] == '_') { - Report.Error (3008, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () ); + Report.Warning (3008, 1, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () ); } return true; } @@ -627,7 +796,11 @@ namespace Mono.CSharp { // internal virtual void GenerateDocComment (DeclSpace ds) { - DocUtil.GenerateDocComment (this, ds); + try { + DocUtil.GenerateDocComment (this, ds); + } catch (Exception e) { + throw new InternalErrorException (this, e); + } } public override IResolveContext ResolveContext { @@ -701,9 +874,10 @@ namespace Mono.CSharp { public TypeContainer PartialContainer; - readonly bool is_generic; + protected readonly bool is_generic; readonly int count_type_params; - readonly int count_current_type_params; + protected TypeParameter[] type_params; + TypeParameter[] type_param_list; // // Whether we are Generic @@ -731,7 +905,7 @@ namespace Mono.CSharp { PartialContainer = null; if (name.TypeArguments != null) { is_generic = true; - count_type_params = count_current_type_params = name.TypeArguments.Count; + count_type_params = name.TypeArguments.Count; } if (parent != null) count_type_params += parent.count_type_params; @@ -753,6 +927,9 @@ namespace Mono.CSharp { return true; } + if (((mc.ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0) + return true; + if (symbol.EnableOverloadChecks (mc)) return true; @@ -762,13 +939,13 @@ namespace Mono.CSharp { return false; } - if (this is RootTypes) { + if (this is ModuleContainer) { Report.Error (101, symbol.Location, "The namespace `{0}' already contains a definition for `{1}'", ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name); } else if (symbol is TypeParameter) { Report.Error (692, symbol.Location, - "Duplicate type parameter `{0}'", name); + "Duplicate type parameter `{0}'", symbol.GetSignatureForError ()); } else { Report.Error (102, symbol.Location, "The type `{0}' already contains a definition for `{1}'", @@ -778,6 +955,11 @@ namespace Mono.CSharp { return false; } + protected void RemoveFromContainer (string name) + { + defined_names.Remove (name); + } + /// /// Returns the MemberCore associated with a given name in the declaration /// space. It doesn't return method based symbols !! @@ -801,6 +983,11 @@ namespace Mono.CSharp { get { return (Parent != null && Parent.Parent == null); } } + public virtual bool IsUnmanagedType () + { + return false; + } + public virtual void CloseType () { if ((caching_flags & Flags.CloseTypeCreated) == 0){ @@ -823,7 +1010,7 @@ namespace Mono.CSharp { } protected virtual TypeAttributes TypeAttr { - get { return CodeGen.Module.DefaultCharSetType; } + get { return Module.DefaultCharSetType; } } /// @@ -831,19 +1018,6 @@ namespace Mono.CSharp { /// public abstract TypeBuilder DefineType (); - /// - /// Define all members, but don't apply any attributes or do anything which may - /// access not-yet-defined classes. This method also creates the MemberCache. - /// - public virtual bool DefineMembers () - { - if (((ModFlags & Modifiers.NEW) != 0) && IsTopLevel) { - Report.Error (1530, Location, "Keyword `new' is not allowed on namespace elements"); - return false; - } - return true; - } - protected void Error_MissingPartialModifier (MemberCore type) { Report.Error (260, type.Location, @@ -851,44 +1025,55 @@ namespace Mono.CSharp { type.GetSignatureForError ()); } + public override void Emit () + { + if (type_params != null) { + int offset = count_type_params - type_params.Length; + for (int i = offset; i < type_params.Length; i++) + CurrentTypeParameters [i - offset].Emit (); + } + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (TypeBuilder); + + base.Emit (); + } + public override string GetSignatureForError () { - if (IsGeneric) { - return SimpleName.RemoveGenericArity (Name) + TypeParameter.GetSignatureForError (CurrentTypeParameters); - } - // Parent.GetSignatureForError - return Name; + return MemberName.GetSignatureForError (); } public bool CheckAccessLevel (Type check_type) { - TypeBuilder tb; - if (this is GenericMethod) + Type tb = TypeBuilder; + + if (this is GenericMethod) { tb = Parent.TypeBuilder; - else - tb = TypeBuilder; + + // FIXME: Generic container does not work with nested generic + // anonymous method stories + if (TypeBuilder == null) + return true; + } check_type = TypeManager.DropGenericTypeArguments (check_type); if (check_type == tb) return true; - - if (TypeBuilder == null) - // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases(). - // However, this is invoked again later -- so safe to return true. - // May also be null when resolving top-level attributes. - return true; + + // TODO: When called from LocalUsingAliasEntry tb is null + // because we are in RootDeclSpace + if (tb == null) + tb = typeof (RootDeclSpace); // // Broken Microsoft runtime, return public for arrays, no matter what // the accessibility is for their underlying class, and they return // NonPublic visibility for pointers // - if (check_type.IsArray || check_type.IsPointer) + if (TypeManager.HasElementType (check_type)) return CheckAccessLevel (TypeManager.GetElementType (check_type)); - if (TypeManager.IsGenericParameter(check_type)) - return true; // FIXME - TypeAttributes check_attr = check_type.Attributes & TypeAttributes.VisibilityMask; switch (check_attr){ @@ -896,23 +1081,14 @@ namespace Mono.CSharp { return true; case TypeAttributes.NotPublic: - - if (TypeBuilder == null) - // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases(). - // However, this is invoked again later -- so safe to return true. - // May also be null when resolving top-level attributes. - return true; - // - // This test should probably use the declaringtype. - // - return check_type.Assembly == TypeBuilder.Assembly || - TypeManager.IsFriendAssembly (check_type.Assembly); + return TypeManager.IsThisOrFriendAssembly (check_type.Assembly); case TypeAttributes.NestedPublic: - return true; + return CheckAccessLevel (check_type.DeclaringType); case TypeAttributes.NestedPrivate: - return NestedAccessible (tb, check_type); + Type declaring = check_type.DeclaringType; + return tb == declaring || TypeManager.IsNestedChildOf (tb, declaring); case TypeAttributes.NestedFamily: // @@ -921,145 +1097,40 @@ namespace Mono.CSharp { return FamilyAccessible (tb, check_type); case TypeAttributes.NestedFamANDAssem: - return ((check_type.Assembly == tb.Assembly) || - TypeManager.IsFriendAssembly (check_type.Assembly)) && + return TypeManager.IsThisOrFriendAssembly (check_type.Assembly) && FamilyAccessible (tb, check_type); case TypeAttributes.NestedFamORAssem: - return (check_type.Assembly == tb.Assembly) || - FamilyAccessible (tb, check_type) || - TypeManager.IsFriendAssembly (check_type.Assembly); + return FamilyAccessible (tb, check_type) || + TypeManager.IsThisOrFriendAssembly (check_type.Assembly); case TypeAttributes.NestedAssembly: - return check_type.Assembly == tb.Assembly || - TypeManager.IsFriendAssembly (check_type.Assembly); + return TypeManager.IsThisOrFriendAssembly (check_type.Assembly); } - Console.WriteLine ("HERE: " + check_attr); - return false; - + throw new NotImplementedException (check_attr.ToString ()); } - protected bool NestedAccessible (Type tb, Type check_type) + static bool FamilyAccessible (Type tb, Type check_type) { Type declaring = check_type.DeclaringType; - return TypeBuilder == declaring || - TypeManager.IsNestedChildOf (TypeBuilder, declaring); + return TypeManager.IsNestedFamilyAccessible (tb, declaring); } - protected bool FamilyAccessible (Type tb, Type check_type) + public bool IsBaseType (Type baseType) { - Type declaring = check_type.DeclaringType; - return TypeManager.IsNestedFamilyAccessible (TypeBuilder, declaring); - } + if (TypeManager.IsInterfaceType (baseType)) + throw new NotImplementedException (); - // Access level of a type. - const int X = 1; - enum AccessLevel { // Each column represents `is this scope larger or equal to Blah scope' - // Public Assembly Protected - Protected = (0 << 0) | (0 << 1) | (X << 2), - Public = (X << 0) | (X << 1) | (X << 2), - Private = (0 << 0) | (0 << 1) | (0 << 2), - Internal = (0 << 0) | (X << 1) | (0 << 2), - ProtectedOrInternal = (0 << 0) | (X << 1) | (X << 2), - } - - static AccessLevel GetAccessLevelFromModifiers (int flags) - { - if ((flags & Modifiers.INTERNAL) != 0) { - - if ((flags & Modifiers.PROTECTED) != 0) - return AccessLevel.ProtectedOrInternal; - else - return AccessLevel.Internal; - - } else if ((flags & Modifiers.PROTECTED) != 0) - return AccessLevel.Protected; - else if ((flags & Modifiers.PRIVATE) != 0) - return AccessLevel.Private; - else - return AccessLevel.Public; - } + Type type = TypeBuilder; + while (type != null) { + if (TypeManager.IsEqual (type, baseType)) + return true; - // What is the effective access level of this? - // TODO: Cache this? - AccessLevel EffectiveAccessLevel { - get { - AccessLevel myAccess = GetAccessLevelFromModifiers (ModFlags); - if (!IsTopLevel && (Parent != null)) - return myAccess & Parent.EffectiveAccessLevel; - return myAccess; + type = type.BaseType; } - } - - // Return the access level for type `t' - static AccessLevel TypeEffectiveAccessLevel (Type t) - { - if (t.IsPublic) - return AccessLevel.Public; - if (t.IsNestedPrivate) - return AccessLevel.Private; - if (t.IsNotPublic) - return AccessLevel.Internal; - - // By now, it must be nested - AccessLevel parent_level = TypeEffectiveAccessLevel (t.DeclaringType); - - if (t.IsNestedPublic) - return parent_level; - if (t.IsNestedAssembly) - return parent_level & AccessLevel.Internal; - if (t.IsNestedFamily) - return parent_level & AccessLevel.Protected; - if (t.IsNestedFamORAssem) - return parent_level & AccessLevel.ProtectedOrInternal; - if (t.IsNestedFamANDAssem) - throw new NotImplementedException ("NestedFamANDAssem not implemented, cant make this kind of type from c# anyways"); - - // nested private is taken care of - - throw new Exception ("I give up, what are you?"); - } - // - // This answers `is the type P, as accessible as a member M which has the - // accessability @flags which is declared as a nested member of the type T, this declspace' - // - public bool AsAccessible (Type p, int flags) - { - // - // 1) if M is private, its accessability is the same as this declspace. - // we already know that P is accessible to T before this method, so we - // may return true. - // - - if ((flags & Modifiers.PRIVATE) != 0) - return true; - - while (p.IsArray || p.IsPointer || p.IsByRef) - p = TypeManager.GetElementType (p); - -#if GMCS_SOURCE - if (p.IsGenericParameter) - return true; - - if (TypeManager.IsGenericType (p)) { - foreach (Type t in p.GetGenericArguments ()) { - if (!AsAccessible (t, flags)) - return false; - } - } -#endif - AccessLevel pAccess = TypeEffectiveAccessLevel (p); - AccessLevel mAccess = this.EffectiveAccessLevel & - GetAccessLevelFromModifiers (flags); - - // for every place from which we can access M, we must - // be able to access P as well. So, we want - // For every bit in M and P, M_i -> P_1 == true - // or, ~ (M -> P) == 0 <-> ~ ( ~M | P) == 0 - - return ~ (~ mAccess | pAccess) == 0; + return false; } private Type LookupNestedTypeInHierarchy (string name) @@ -1100,7 +1171,6 @@ namespace Mono.CSharp { if ((t == null) || !CheckAccessLevel (t)) continue; -#if GMCS_SOURCE if (!TypeManager.IsGenericType (current_type)) return t; @@ -1109,6 +1179,7 @@ namespace Mono.CSharp { for (int i = 0; i < args.Length; i++) targs [i] = args [i]; +#if GMCS_SOURCE t = t.MakeGenericType (targs); #endif @@ -1118,7 +1189,7 @@ namespace Mono.CSharp { return null; } - public virtual ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name) + public virtual ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc) { return null; } @@ -1136,6 +1207,7 @@ namespace Mono.CSharp { return (FullNamedExpression) Cache [name]; FullNamedExpression e; + int errors = Report.Errors; Type t = LookupNestedTypeInHierarchy (name); if (t != null) e = new TypeExpression (t, Location.Null); @@ -1144,7 +1216,9 @@ namespace Mono.CSharp { else e = NamespaceEntry.LookupNamespaceOrType (this, name, loc, ignore_cs0104); - Cache [name] = e; + if (errors == Report.Errors) + Cache [name] = e; + return e; } @@ -1169,54 +1243,19 @@ namespace Mono.CSharp { get; } - public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) + public virtual ModuleContainer Module { + get { return Parent.Module; } + } + + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa) { - if (a.Type == TypeManager.required_attr_type) { + if (a.Type == pa.Required) { Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types"); return; } TypeBuilder.SetCustomAttribute (cb); } - // - // Extensions for generics - // - TypeParameter[] type_params; - TypeParameter[] type_param_list; - - protected string GetInstantiationName () - { - StringBuilder sb = new StringBuilder (Name); - sb.Append ("<"); - for (int i = 0; i < type_param_list.Length; i++) { - if (i > 0) - sb.Append (","); - sb.Append (type_param_list [i].Name); - } - sb.Append (">"); - return sb.ToString (); - } - - bool check_type_parameter (ArrayList list, int start, string name) - { - for (int i = 0; i < start; i++) { - TypeParameter param = (TypeParameter) list [i]; - - if (param.Name != name) - continue; - - Report.SymbolRelatedToPreviousError (Parent); - // TODO: Location is wrong (parent instead of child) - Report.Warning (693, 3, Location, - "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'", - name, Parent.GetSignatureForError ()); - - return false; - } - - return true; - } - TypeParameter[] initialize_type_params () { if (type_param_list != null) @@ -1226,20 +1265,28 @@ namespace Mono.CSharp { if (this is GenericMethod) the_parent = null; - int start = 0; ArrayList list = new ArrayList (); if (the_parent != null && the_parent.IsGeneric) { // FIXME: move generics info out of DeclSpace TypeParameter[] parent_params = the_parent.PartialContainer.TypeParameters; - start = parent_params.Length; list.AddRange (parent_params); } int count = type_params != null ? type_params.Length : 0; for (int i = 0; i < count; i++) { TypeParameter param = type_params [i]; - check_type_parameter (list, start, param.Name); list.Add (param); + if (Parent.IsGeneric) { + foreach (TypeParameter tp in Parent.PartialContainer.CurrentTypeParameters) { + if (tp.Name != param.Name) + continue; + + Report.SymbolRelatedToPreviousError (tp.Location, null); + Report.Warning (693, 3, param.Location, + "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'", + param.Name, Parent.GetSignatureForError ()); + } + } } type_param_list = new TypeParameter [list.Count]; @@ -1287,9 +1334,14 @@ namespace Mono.CSharp { } } + Variance variance = name.Variance; + if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) { + Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates"); + variance = Variance.None; + } + type_params [i] = new TypeParameter ( - Parent, this, name.Name, constraints, name.OptAttributes, - Location); + Parent, this, name.Name, constraints, name.OptAttributes, variance, Location); AddToContainer (type_params [i], name.Name); } @@ -1319,12 +1371,12 @@ namespace Mono.CSharp { get { if (!IsGeneric) throw new InvalidOperationException (); - if ((PartialContainer != null) && (PartialContainer != this)) - return PartialContainer.CurrentTypeParameters; - if (type_params != null) - return type_params; - else + + // TODO: Something is seriously broken here + if (type_params == null) return new TypeParameter [0]; + + return type_params; } } @@ -1334,12 +1386,6 @@ namespace Mono.CSharp { } } - public int CountCurrentTypeParameters { - get { - return count_current_type_params; - } - } - public TypeParameterExpr LookupGeneric (string name, Location loc) { if (!IsGeneric) @@ -1407,11 +1453,8 @@ namespace Mono.CSharp { else { Report.SymbolRelatedToPreviousError ((DeclSpace)val); } -#if GMCS_SOURCE + Report.Warning (3005, 1, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ()); -#else - Report.Error (3005, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ()); -#endif return true; } } @@ -1809,9 +1852,10 @@ namespace Mono.CSharp { AddMember (mi.MemberType, GetBindingFlags (mc.ModFlags), Container, mi.Name, mi); } - public void AddGenericMember (MemberInfo mi, MemberCore mc) + public void AddGenericMember (MemberInfo mi, InterfaceMemberBase mc) { - AddMember (mi.MemberType, GetBindingFlags (mc.ModFlags), Container, mc.MemberName.Basename, mi); + AddMember (mi.MemberType, GetBindingFlags (mc.ModFlags), Container, + MemberName.MakeName (mc.GetFullName (mc.MemberName), mc.MemberName.TypeArguments), mi); } public void AddNestedType (DeclSpace type) @@ -2270,9 +2314,6 @@ namespace Mono.CSharp { return null; EntryType entry_type = EntryType.Static | EntryType.Method | EntryType.NotExtensionMethod; - if (publicOnly) { - entry_type |= EntryType.Public; - } EntryType found_entry_type = entry_type & ~EntryType.NotExtensionMethod; ArrayList candidates = null; @@ -2280,8 +2321,18 @@ namespace Mono.CSharp { if ((entry.EntryType & entry_type) == found_entry_type) { MethodBase mb = (MethodBase)entry.Member; + // Simple accessibility check + if ((entry.EntryType & EntryType.Public) == 0 && publicOnly) { + MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask; + if (ma != MethodAttributes.Assembly && ma != MethodAttributes.FamORAssem) + continue; + + if (!TypeManager.IsThisOrFriendAssembly (mb.DeclaringType.Assembly)) + continue; + } + IMethodData md = TypeManager.GetMethod (mb); - ParameterData pd = md == null ? + AParametersCollection pd = md == null ? TypeManager.GetParameterData (mb) : md.ParameterInfo; Type ex_type = pd.ExtensionMethodType; @@ -2309,7 +2360,7 @@ namespace Mono.CSharp { // Because the MemberCache holds members from this class and all the base classes, // we can avoid tons of reflection stuff. // - public MemberInfo FindMemberToOverride (Type invocation_type, string name, Type [] param_types, GenericMethod generic_method, bool is_property) + public MemberInfo FindMemberToOverride (Type invocation_type, string name, AParametersCollection parameters, GenericMethod generic_method, bool is_property) { ArrayList applicable; if (method_hash != null && !is_property) @@ -2331,22 +2382,19 @@ namespace Mono.CSharp { PropertyInfo pi = null; MethodInfo mi = null; FieldInfo fi = null; - Type [] cmp_attrs = null; + AParametersCollection cmp_attrs; if (is_property) { if ((entry.EntryType & EntryType.Field) != 0) { fi = (FieldInfo)entry.Member; - - // TODO: For this case we ignore member type - //fb = TypeManager.GetField (fi); - //cmp_attrs = new Type[] { fb.MemberType }; + cmp_attrs = ParametersCompiled.EmptyReadOnlyParameters; } else { pi = (PropertyInfo) entry.Member; - cmp_attrs = TypeManager.GetArgumentTypes (pi); + cmp_attrs = TypeManager.GetParameterData (pi); } } else { mi = (MethodInfo) entry.Member; - cmp_attrs = TypeManager.GetParameterData (mi).Types; + cmp_attrs = TypeManager.GetParameterData (mi); } if (fi != null) { @@ -2369,7 +2417,7 @@ namespace Mono.CSharp { // // Check for assembly methods // - if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder) + if (fi.DeclaringType.Assembly != CodeGen.Assembly.Builder) continue; break; } @@ -2379,14 +2427,23 @@ namespace Mono.CSharp { // // Check the arguments // - if (cmp_attrs.Length != param_types.Length) + if (cmp_attrs.Count != parameters.Count) continue; int j; - for (j = 0; j < cmp_attrs.Length; ++j) - if (!TypeManager.IsEqual (param_types [j], cmp_attrs [j])) + for (j = 0; j < cmp_attrs.Count; ++j) { + // + // LAMESPEC: No idea why `params' modifier is ignored + // + if ((parameters.FixedParameters [j].ModFlags & ~Parameter.Modifier.PARAMS) != + (cmp_attrs.FixedParameters [j].ModFlags & ~Parameter.Modifier.PARAMS)) + break; + + if (!TypeManager.IsEqual (parameters.Types [j], cmp_attrs.Types [j])) break; - if (j < cmp_attrs.Length) + } + + if (j < cmp_attrs.Count) continue; // @@ -2394,9 +2451,9 @@ namespace Mono.CSharp { // if (mi != null) { Type [] cmpGenArgs = TypeManager.GetGenericArguments (mi); - if (generic_method == null && cmpGenArgs.Length != 0) + if (generic_method == null && cmpGenArgs != null && cmpGenArgs.Length != 0) continue; - if (generic_method != null && cmpGenArgs.Length != generic_method.TypeParameters.Length) + if (generic_method != null && cmpGenArgs != null && cmpGenArgs.Length != generic_method.TypeParameters.Length) continue; } @@ -2429,7 +2486,7 @@ namespace Mono.CSharp { // // Check for assembly methods // - if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder) + if (!TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) continue; break; } @@ -2474,8 +2531,8 @@ namespace Mono.CSharp { // Does exist easier way how to detect indexer ? if ((entry.EntryType & EntryType.Property) != 0) { - Type[] arg_types = TypeManager.GetArgumentTypes ((PropertyInfo)entry.Member); - if (arg_types.Length > 0) + AParametersCollection arg_types = TypeManager.GetParameterData ((PropertyInfo)entry.Member); + if (arg_types.Count > 0) continue; } } @@ -2507,31 +2564,31 @@ namespace Mono.CSharp { // TODO: Does anyone know easier way how to detect that member is internal ? switch (member_entry.EntryType & EntryType.MaskType) { - case EntryType.Constructor: - continue; - - case EntryType.Field: - if ((((FieldInfo)member_entry.Member).Attributes & (FieldAttributes.Assembly | FieldAttributes.Public)) == FieldAttributes.Assembly) - continue; - break; - - case EntryType.Method: - if ((((MethodInfo)member_entry.Member).Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly) - continue; - break; - - case EntryType.Property: - PropertyInfo pi = (PropertyInfo)member_entry.Member; - if (pi.GetSetMethod () == null && pi.GetGetMethod () == null) - continue; - break; - - case EntryType.Event: - EventInfo ei = (EventInfo)member_entry.Member; - MethodInfo mi = ei.GetAddMethod (); - if ((mi.Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly) - continue; - break; + case EntryType.Constructor: + continue; + + case EntryType.Field: + if ((((FieldInfo)member_entry.Member).Attributes & (FieldAttributes.Assembly | FieldAttributes.Public)) == FieldAttributes.Assembly) + continue; + break; + + case EntryType.Method: + if ((((MethodInfo)member_entry.Member).Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly) + continue; + break; + + case EntryType.Property: + PropertyInfo pi = (PropertyInfo)member_entry.Member; + if (pi.GetSetMethod () == null && pi.GetGetMethod () == null) + continue; + break; + + case EntryType.Event: + EventInfo ei = (EventInfo)member_entry.Member; + MethodInfo mi = ei.GetAddMethod (); + if ((mi.Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly) + continue; + break; } string lcase = ((string)entry.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture); locase_table [lcase] = member_entry.Member; @@ -2568,7 +2625,7 @@ namespace Mono.CSharp { MethodBase method_to_compare = (MethodBase)entry.Member; AttributeTester.Result result = AttributeTester.AreOverloadedMethodParamsClsCompliant ( - method.ParameterTypes, TypeManager.GetParameterData (method_to_compare).Types); + method.Parameters, TypeManager.GetParameterData (method_to_compare)); if (result == AttributeTester.Result.Ok) continue; @@ -2582,19 +2639,23 @@ namespace Mono.CSharp { Report.SymbolRelatedToPreviousError (entry.Member); switch (result) { - case AttributeTester.Result.RefOutArrayError: - Report.Error (3006, method.Location, "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", method.GetSignatureForError ()); - continue; - case AttributeTester.Result.ArrayArrayError: - Report.Error (3007, method.Location, "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", method.GetSignatureForError ()); - continue; + case AttributeTester.Result.RefOutArrayError: + Report.Warning (3006, 1, method.Location, + "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", + method.GetSignatureForError ()); + continue; + case AttributeTester.Result.ArrayArrayError: + Report.Warning (3007, 1, method.Location, + "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", + method.GetSignatureForError ()); + continue; } throw new NotImplementedException (result.ToString ()); } } - public bool CheckExistingMembersOverloads (MemberCore member, string name, Parameters parameters) + public bool CheckExistingMembersOverloads (MemberCore member, string name, ParametersCompiled parameters) { ArrayList entries = (ArrayList)member_hash [name]; if (entries == null) @@ -2608,17 +2669,18 @@ namespace Mono.CSharp { return true; Type [] p_types; - ParameterData pd = null; + AParametersCollection pd; if ((ce.EntryType & EntryType.Property) != 0) { - p_types = TypeManager.GetArgumentTypes ((PropertyInfo) ce.Member); + pd = TypeManager.GetParameterData ((PropertyInfo) ce.Member); + p_types = pd.Types; } else { MethodBase mb = (MethodBase) ce.Member; -#if GMCS_SOURCE + // TODO: This is more like a hack, because we are adding generic methods // twice with and without arity name - if (mb.IsGenericMethod && !member.MemberName.IsGeneric) + if (TypeManager.IsGenericMethod (mb) && !member.MemberName.IsGeneric) continue; -#endif + pd = TypeManager.GetParameterData (mb); p_types = pd.Types; } @@ -2630,15 +2692,20 @@ namespace Mono.CSharp { int ii = method_param_count - 1; Type type_a, type_b; do { - type_a = parameters.ParameterType (ii); + type_a = parameters.Types [ii]; type_b = p_types [ii]; + #if GMCS_SOURCE - if (type_a.IsGenericParameter && type_a.DeclaringMethod != null) - type_a = null; + if (TypeManager.IsGenericParameter (type_a) && type_a.DeclaringMethod != null) + type_a = typeof (TypeParameter); - if (type_b.IsGenericParameter && type_b.DeclaringMethod != null) - type_b = null; + if (TypeManager.IsGenericParameter (type_b) && type_b.DeclaringMethod != null) + type_b = typeof (TypeParameter); #endif + if ((pd.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF) != + (parameters.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF)) + type_a = null; + } while (type_a == type_b && ii-- != 0); if (ii >= 0) @@ -2656,9 +2723,9 @@ namespace Mono.CSharp { // // Report difference in parameter modifiers only // - if (pd != null && !(member is AbstractPropertyEventMethod)) { + if (pd != null && member is MethodCore) { ii = method_param_count; - while (ii-- != 0 && parameters.ParameterModifier (ii) == pd.ParameterModifier (ii) && + while (ii-- != 0 && parameters.FixedParameters [ii].ModFlags == pd.FixedParameters [ii].ModFlags && parameters.ExtensionMethodType == pd.ExtensionMethodType); if (ii >= 0) { @@ -2673,9 +2740,15 @@ namespace Mono.CSharp { "A partial method declaration and partial method implementation must be both an extension method or neither"); } } else { - Report.Error (663, member.Location, - "An overloaded method `{0}' cannot differ on use of parameter modifiers only", - member.GetSignatureForError ()); + if (member is Constructor) { + Report.Error (851, member.Location, + "Overloaded contructor `{0}' cannot differ on use of parameter modifiers only", + member.GetSignatureForError ()); + } else { + Report.Error (663, member.Location, + "Overloaded method `{0}' cannot differ on use of parameter modifiers only", + member.GetSignatureForError ()); + } } return false; }