I forgot to attach the patch ;-) Carlos.
El vie, 28-10-2005 a las 16:23 +0530, Raja R Harinath escribió: > Hi, > > Carlos Alberto Cortez <[EMAIL PROTECTED]> writes: > > > The attached patch implements friend access for class members (methods, > > properties, fields). > > > > I'm not including the type-check section, since that part will be > > modified (next merge to gmcs) and I'm waiting for that to happen. > > However, that change should be small (I will send the patch). > > I have completed the merge of the relevant parts. Please post an > updated patch. > > Meanwhile, I have some comments: > > [snip] > > @@ -2646,25 +2726,38 @@ > > MethodBase mb = (MethodBase) m; > > MethodAttributes ma = mb.Attributes & > > MethodAttributes.MemberAccessMask; > > > > + if (ma == MethodAttributes.Public) > > + return true; > > Ok. > > > if (ma == MethodAttributes.Private) > > return private_ok || > > IsPrivateAccessible > > (invocation_type, m.DeclaringType) || > > IsNestedChildOf > > (invocation_type, m.DeclaringType); > > > > - if (invocation_assembly == > > mb.DeclaringType.Assembly) { > > + if (invocation_assembly == > > mb.DeclaringType.Assembly) > > if (ma == MethodAttributes.Assembly || > > ma == MethodAttributes.FamORAssem) > > return true; > > - } else { > > - if (ma == MethodAttributes.Assembly || > > ma == MethodAttributes.FamANDAssem) > > - return false; > > I would retain the old code, and change the check to: > > if (invocation_assembly == mb.DeclaringType.Assembly || > TypeManager.InternalsVisibleTo (invocation_assembly, > mb.DeclaringType.Assembly)) > > > + > > + if (ma == MethodAttributes.Family || > > + ma == MethodAttributes.FamANDAssem || > > + ma == MethodAttributes.FamORAssem) { > > + if (!CheckValidFamilyAccess > > (mb.IsStatic, m)) { > > + if (ma == > > MethodAttributes.Family || ma == MethodAttributes.FamANDAssem) > > + return false; > > + } else { > > + // We are valid > > + if (ma == > > MethodAttributes.Family || ma == MethodAttributes.FamORAssem) > > + return true; > > + > > + // Check for FamANDAssem > > + if (invocation_assembly == > > mb.DeclaringType.Assembly) > > + return true; > > + } > > } > > - if (ma == MethodAttributes.Family || > > - ma == MethodAttributes.FamANDAssem || > > - ma == MethodAttributes.FamORAssem) > > - return CheckValidFamilyAccess > > (mb.IsStatic, m); > > I don't like this too much. I'd much rather keep the old code. > > - Hari
Index: typemanager.cs =================================================================== --- typemanager.cs (revisión: 52315) +++ typemanager.cs (copia de trabajo) @@ -252,6 +252,8 @@ static Hashtable fieldbuilders_to_fields; static Hashtable fields; + static PtrHashtable assembly_internals_vis_attrs; + struct Signature { public string name; public Type [] args; @@ -274,6 +276,8 @@ priv_fields_events = null; type_hash = null; + + assembly_internals_vis_attrs = null; CleanUpGenerics (); TypeHandle.CleanUp (); @@ -375,6 +379,8 @@ fieldbuilders_to_fields = new Hashtable (); fields = new Hashtable (); type_hash = new DoubleHash (); + + assembly_internals_vis_attrs = new PtrHashtable (); InitGenerics (); } @@ -1654,6 +1660,80 @@ return false; } + // + // Checks whether `extern_type' is friend of the output assembly + // + public static bool IsFriendAssembly (Assembly assembly) + { + if (assembly_internals_vis_attrs.Contains (assembly)) + return (bool)(assembly_internals_vis_attrs [assembly]); + + object [] attrs = assembly.GetCustomAttributes (internals_visible_attr_type, false); + if (attrs.Length == 0) { + AddFriendAssembly (assembly, false); + return false; + } + + AssemblyName this_name = CodeGen.Assembly.Name; + byte [] this_token = this_name.GetPublicKeyToken (); + bool is_friend = false; + foreach (object o in attrs) { + InternalsVisibleToAttribute attr = o as InternalsVisibleToAttribute; + if (attr.AssemblyName == null || attr.AssemblyName.Length == 0) + continue; + + AssemblyName aname = null; + try { + aname = new AssemblyName (attr.AssemblyName); + } catch (FileLoadException) { + } catch (ArgumentException) { + } + + if (aname == null || aname.Name != this_name.Name) + continue; + + byte [] key_token = aname.GetPublicKeyToken (); + if (key_token != null) { + if (this_token == null) { + // Same name, but key token is null + Error_FriendAccessNameNotMatching (aname.FullName); + break; + } + + if (!CompareKeyTokens (this_token, key_token)) + continue; + } + + is_friend = true; + break; + } + + AddFriendAssembly (assembly, is_friend); + return is_friend; + } + + static bool CompareKeyTokens (byte [] token1, byte [] token2) + { + for (int i = 0; i < token1.Length; i++) + if (token1 [i] != token2 [i]) + return false; + + return true; + } + + static string this_fullname; + + static void Error_FriendAccessNameNotMatching (string other_name) + { + if (this_fullname == null) + this_fullname = CodeGen.Assembly.Name.FullName; + + Report.Error (281, "Friend access was granted to `" + other_name + + "', but the output assembly is named `" + this_fullname + + "'. Try adding a reference to `" + other_name + + "' or change the output assembly name to match it."); + } + // // Do the right thing when returning the element type of an // array type based on whether we are compiling corlib or not @@ -2478,12 +2558,16 @@ MethodBase mb = (MethodBase) m; MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask; + if (ma == MethodAttributes.Public) + return true; + if (ma == MethodAttributes.Private) return private_ok || IsPrivateAccessible (invocation_type, m.DeclaringType) || IsNestedChildOf (invocation_type, m.DeclaringType); - if (invocation_assembly == mb.DeclaringType.Assembly) { + if (invocation_assembly == mb.DeclaringType.Assembly || + TypeManager.IsFriendAssembly (mb.DeclaringType.Assembly)) { if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) return true; } else { @@ -2491,25 +2575,24 @@ return false; } - if (ma == MethodAttributes.Family || - ma == MethodAttributes.FamANDAssem || - ma == MethodAttributes.FamORAssem) - return CheckValidFamilyAccess (mb.IsStatic, m); - - // Public. - return true; + // Family, FamORAssem or FamANDAssem + return CheckValidFamilyAccess (mb.IsStatic, m); } if (m is FieldInfo){ FieldInfo fi = (FieldInfo) m; FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask; + if (fa == FieldAttributes.Public) + return true; + if (fa == FieldAttributes.Private) return private_ok || IsPrivateAccessible (invocation_type, m.DeclaringType) || IsNestedChildOf (invocation_type, m.DeclaringType); - if (invocation_assembly == fi.DeclaringType.Assembly) { + if (invocation_assembly == fi.DeclaringType.Assembly || + TypeManager.IsFriendAssembly (fi.DeclaringType.Assembly)) { if (fa == FieldAttributes.Assembly || fa == FieldAttributes.FamORAssem) return true; } else { @@ -2517,13 +2600,8 @@ return false; } - if (fa == FieldAttributes.Family || - fa == FieldAttributes.FamANDAssem || - fa == FieldAttributes.FamORAssem) - return CheckValidFamilyAccess (fi.IsStatic, m); - - // Public. - return true; + // Family, FamORAssem or FamANDAssem + return CheckValidFamilyAccess (fi.IsStatic, m); } // @@ -2784,6 +2862,11 @@ } return false; } + + static void AddFriendAssembly (Assembly assembly, bool is_friend) + { + assembly_internals_vis_attrs.Add (assembly, is_friend); + } #endregion Index: namespace.cs =================================================================== --- namespace.cs (revisión: 52314) +++ namespace.cs (copia de trabajo) @@ -112,12 +112,17 @@ if (t.IsPointer) throw new InternalErrorException ("Use GetPointerType() to get a pointer"); + TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask; + if (ta == TypeAttributes.NestedPrivate) + return null; + if (ta == TypeAttributes.NotPublic || - ta == TypeAttributes.NestedPrivate || - ta == TypeAttributes.NestedAssembly || - ta == TypeAttributes.NestedFamANDAssem) - return null; + ta == TypeAttributes.NestedAssembly || + /*ta == TypeAttributes.NestedFamORAssem ||*/ + ta == TypeAttributes.NestedFamANDAssem) + if (!TypeManager.IsFriendAssembly (t.Assembly)) + return null; return t; } Index: ecore.cs =================================================================== --- ecore.cs (revisión: 52315) +++ ecore.cs (copia de trabajo) @@ -156,6 +156,9 @@ must_do_cs1540_check = false; // by default we do not check for this + if (ma == MethodAttributes.Public) + return true; + // // If only accessible to the current class or children // @@ -163,7 +166,8 @@ return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) || TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType); - if (mi.DeclaringType.Assembly == invocation_type.Assembly) { + if (mi.DeclaringType.Assembly == invocation_type.Assembly || + TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) { if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) return true; } else { @@ -173,18 +177,12 @@ // Family and FamANDAssem require that we derive. // FamORAssem requires that we derive if in different assemblies. - if (ma == MethodAttributes.Family || - ma == MethodAttributes.FamANDAssem || - ma == MethodAttributes.FamORAssem) { - if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType)) - return false; + if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType)) + return false; - if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType)) - must_do_cs1540_check = true; + if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType)) + must_do_cs1540_check = true; - return true; - } - return true; } Index: decl.cs =================================================================== --- decl.cs (revisión: 52314) +++ decl.cs (copia de trabajo) @@ -925,7 +925,8 @@ // // This test should probably use the declaringtype. // - return check_type.Assembly == TypeBuilder.Assembly; + return check_type.Assembly == TypeBuilder.Assembly || + TypeManager.IsFriendAssembly (check_type.Assembly); case TypeAttributes.NestedPublic: return true; @@ -940,15 +941,18 @@ return FamilyAccessible (tb, check_type); case TypeAttributes.NestedFamANDAssem: - return (check_type.Assembly == tb.Assembly) && + return ((check_type.Assembly == tb.Assembly) || + TypeManager.IsFriendAssembly (check_type.Assembly)) && FamilyAccessible (tb, check_type); case TypeAttributes.NestedFamORAssem: return (check_type.Assembly == tb.Assembly) || - FamilyAccessible (tb, check_type); + FamilyAccessible (tb, check_type) || + TypeManager.IsFriendAssembly (check_type.Assembly); case TypeAttributes.NestedAssembly: - return check_type.Assembly == tb.Assembly; + return check_type.Assembly == tb.Assembly || + TypeManager.IsFriendAssembly (check_type.Assembly); } Console.WriteLine ("HERE: " + check_attr);
friend-test.tar.gz
Description: application/compressed-tar
_______________________________________________ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list