X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdecl.cs;h=f98c5ae909d34127577625f819d5228ea96b7732;hb=398ddf57679d166c65418736cdbd540ed5b9e534;hp=1d2ded189e3caed877495ac2baa59ba92c1b7a88;hpb=44b4f6a73931d5000dab72ec6f26182ec7b7cfde;p=mono.git diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs index 1d2ded189e3..f98c5ae909d 100644 --- a/mcs/mcs/decl.cs +++ b/mcs/mcs/decl.cs @@ -4,10 +4,10 @@ // 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 // @@ -130,7 +130,7 @@ namespace Mono.CSharp { return MakeName (Name, TypeArguments); } - public Expression GetTypeExpression () + public ATypeNameExpression GetTypeExpression () { if (Left == null) { if (TypeArguments != null) @@ -142,7 +142,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 (); @@ -164,31 +164,29 @@ namespace Mono.CSharp { } } - public string FullName { - get { - if (TypeArguments != null) - return Name + "<" + TypeArguments + ">"; - else - return Name; - } - } - public string MethodName { get { string connect = is_double_colon ? "::" : "."; if (Left != null) - return Left.FullName + connect + Name; + return Left.FullyQualifiedName + connect + Name; else return Name; } } - + + // Please use this only for error reporting. For normal uses, just use the Equals and GetHashCode methods that make + // MemberName a proper hash key, and avoid tons of memory allocations + string FullyQualifiedName { + get { return TypeArguments == null ? MethodName : MethodName + "<" + TypeArguments.GetSignatureForError () + ">"; } + } + 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) @@ -353,7 +351,7 @@ namespace Mono.CSharp { member_name = new_name; cached_name = null; } - + protected bool CheckAbstractAndExtern (bool has_block) { if (Parent.PartialContainer.Kind == Kind.Interface) @@ -385,7 +383,32 @@ namespace Mono.CSharp { } 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) && (Name != "Finalize")) { + Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", + GetSignatureForError ()); + return; + } + } public abstract bool Define (); @@ -441,7 +464,7 @@ namespace Mono.CSharp { caching_flags &= ~Flags.Obsolete_Undetected; - if (OptAttributes == null) + if (OptAttributes == null || TypeManager.obsolete_attribute_type == null) return null; Attribute obsolete_attr = OptAttributes.Search ( @@ -473,6 +496,159 @@ namespace Mono.CSharp { 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 (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 (!IsAccessibleAs (t)) + return false; + } + } +#endif + + 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; + } + + return true; + } + /// /// Analyze whether CLS-Compliant verification must be execute for this MemberCore. /// @@ -519,7 +695,7 @@ namespace Mono.CSharp { caching_flags &= ~Flags.HasCompliantAttribute_Undetected; - if (OptAttributes != null) { + if (OptAttributes != null && TypeManager.cls_compliant_attribute_type != null) { Attribute cls_attribute = OptAttributes.Search ( TypeManager.cls_compliant_attribute_type); if (cls_attribute != null) { @@ -627,7 +803,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 +881,8 @@ 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; // // Whether we are Generic @@ -731,7 +910,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; @@ -851,10 +1030,23 @@ namespace Mono.CSharp { type.GetSignatureForError ()); } + public override void Emit () + { +#if GMCS_SOURCE + 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 (); + } +#endif + + base.Emit (); + } + public override string GetSignatureForError () { if (IsGeneric) { - return SimpleName.RemoveGenericArity (Name) + TypeParameter.GetSignatureForError (CurrentTypeParameters); + return SimpleName.RemoveGenericArity (Name) + TypeParameter.GetSignatureForError (type_params); } // Parent.GetSignatureForError return Name; @@ -902,11 +1094,8 @@ namespace Mono.CSharp { // 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; @@ -921,18 +1110,15 @@ 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); @@ -953,113 +1139,20 @@ namespace Mono.CSharp { return TypeManager.IsNestedFamilyAccessible (TypeBuilder, declaring); } - // 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) + public bool IsBaseType (Type baseType) { - 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; - } + if (TypeManager.IsInterfaceType (baseType)) + throw new NotImplementedException (); - // 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; - } - } - - // 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; + Type type = TypeBuilder; + while (type != null) { + if (TypeManager.IsEqual (type, baseType)) + return true; - if (TypeManager.IsGenericType (p)) { - foreach (Type t in p.GetGenericArguments ()) { - if (!AsAccessible (t, flags)) - return false; - } + type = type.BaseType; } -#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) @@ -1118,7 +1211,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; } @@ -1184,22 +1277,9 @@ namespace Mono.CSharp { // // Extensions for generics // - TypeParameter[] type_params; + protected 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++) { @@ -1322,12 +1402,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; } } @@ -1337,12 +1417,6 @@ namespace Mono.CSharp { } } - public int CountCurrentTypeParameters { - get { - return count_current_type_params; - } - } - public TypeParameterExpr LookupGeneric (string name, Location loc) { if (!IsGeneric) @@ -2432,7 +2506,7 @@ namespace Mono.CSharp { // // Check for assembly methods // - if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder) + if (!TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) continue; break; }