2008-06-11 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / decl.cs
index 67acf31d26073b1b7ccf08974c41f6fd06b067a0..f98c5ae909d34127577625f819d5228ea96b7732 100644 (file)
@@ -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)
@@ -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 ();
 
@@ -570,7 +593,7 @@ namespace Mono.CSharp {
                                        switch (pAccess) {
                                                case AccessLevel.Internal:
                                                        if (al == AccessLevel.Private || al == AccessLevel.Internal)
-                                                               same_access_restrictions = CodeGen.Assembly.Builder == p.Assembly || TypeManager.IsFriendAssembly (p.Assembly);
+                                                               same_access_restrictions = TypeManager.IsThisOrFriendAssembly (p.Assembly);
 
                                                        break;
 
@@ -598,10 +621,10 @@ namespace Mono.CSharp {
                                                        if (al == AccessLevel.Protected)
                                                                same_access_restrictions = mc.Parent.IsBaseType (p_parent);
                                                        else if (al == AccessLevel.Internal)
-                                                               same_access_restrictions = CodeGen.Assembly.Builder == p.Assembly || TypeManager.IsFriendAssembly (p.Assembly);
+                                                               same_access_restrictions = TypeManager.IsThisOrFriendAssembly (p.Assembly);
                                                        else if (al == AccessLevel.ProtectedOrInternal)
                                                                same_access_restrictions = mc.Parent.IsBaseType (p_parent) &&
-                                                                       (CodeGen.Assembly.Builder == p.Assembly || TypeManager.IsFriendAssembly (p.Assembly));
+                                                                       TypeManager.IsThisOrFriendAssembly (p.Assembly);
 
                                                        break;
 
@@ -858,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
@@ -888,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;
@@ -1008,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;
@@ -1059,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;
@@ -1078,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);
@@ -1182,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;
                }
@@ -1248,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++) {
@@ -1386,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;
                        }
                }
 
@@ -1401,12 +1417,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public int CountCurrentTypeParameters {
-                       get {
-                               return count_current_type_params;
-                       }
-               }
-
                public TypeParameterExpr LookupGeneric (string name, Location loc)
                {
                        if (!IsGeneric)
@@ -2496,7 +2506,7 @@ namespace Mono.CSharp {
                                        //
                                        // Check for assembly methods
                                        //
-                                       if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder && !TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly))
+                                       if (!TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly))
                                                continue;
                                        break;
                                }