When checking override base method also check for declaring type visibility
authorMarek Safar <marek.safar@gmail.com>
Thu, 14 Jun 2012 13:00:51 +0000 (14:00 +0100)
committerMarek Safar <marek.safar@gmail.com>
Thu, 14 Jun 2012 13:01:49 +0000 (14:01 +0100)
mcs/errors/CS0122-8-lib.il [new file with mode: 0644]
mcs/errors/Makefile
mcs/errors/cs0122-8.cs [new file with mode: 0644]
mcs/mcs/ecore.cs
mcs/mcs/import.cs
mcs/tests/test-846-lib.il [new file with mode: 0644]
mcs/tests/test-846.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

diff --git a/mcs/errors/CS0122-8-lib.il b/mcs/errors/CS0122-8-lib.il
new file mode 100644 (file)
index 0000000..6414203
--- /dev/null
@@ -0,0 +1,74 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly 'CS0108-8-lib'
+{
+}
+
+.module 'CS0108-8-lib.dll'
+
+
+.class public auto ansi beforefieldinit A
+       extends [mscorlib]System.Object
+{
+  .class auto ansi nested family beforefieldinit AA
+         extends [mscorlib]System.Object
+  {
+    .method public hidebysig newslot virtual 
+            instance void  Foo() cil managed
+    {
+      ret
+    }
+
+    .method public hidebysig specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      ldarg.0
+      call       instance void [mscorlib]System.Object::.ctor()
+      ret
+    }
+
+  }
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    ldarg.0
+    call       instance void [mscorlib]System.Object::.ctor()
+    ret
+  }
+
+}
+
+.class public auto ansi beforefieldinit B
+       extends A
+{
+  .class auto ansi nested public beforefieldinit BB
+         extends A/AA
+  {
+    .method public hidebysig virtual instance void 
+            Foo() cil managed
+    {
+      ret
+    }
+
+    .method public hidebysig specialname rtspecialname 
+            instance void  .ctor() cil managed
+    {
+      ldarg.0
+      call       instance void A/AA::.ctor()
+      ret
+    }
+
+  }
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    ldarg.0
+    call       instance void A::.ctor()
+    ret
+  }
+
+}
index 57ff9ef44909738d6632f1a0b9f7145c014f8eeb..96085dde45b66682c3804a8fee69b59d0533f1b6 100644 (file)
@@ -22,7 +22,7 @@ DISTFILES = \
 
 TEST_SUPPORT_FILES = \
        CS0012-lib.dll CS0012-2-lib.dll CS0012-3-lib.dll CS0012-4-lib.dll CS0012-5-lib.dll CS0012-6-lib.dll CS0012-9-lib.dll CS0012-10-lib.dll CS0012-11-lib.dll CS0012-12-lib.dll CS0012-13-lib.dll CS0012-14-lib.dll CS0012-15-lib.dll CS0012-16-lib.dll CS0029-26-lib.dll \
-       CS0103-2-lib.dll CS0118-2-lib.dll CS0122-10-lib.dll CS0122-14-lib.dll CS0122-15-lib.dll CS0122-19-lib.dll CS0122-35-lib.dll CS0122-36-lib.dll CS0143-lib.dll CS0144-3-lib.dll CS0165-19-lib.dll \
+       CS0103-2-lib.dll CS0118-2-lib.dll CS0122-8-lib.dll CS0122-10-lib.dll CS0122-14-lib.dll CS0122-15-lib.dll CS0122-19-lib.dll CS0122-35-lib.dll CS0122-36-lib.dll CS0143-lib.dll CS0144-3-lib.dll CS0165-19-lib.dll \
        CS0205-3-lib.dll CS0229-3-lib.dll CS0229-4-lib.dll CS0266-25-lib.dll \
        CS0315-2-lib.dll \
        CS0425-7-lib.dll CS0433-lib.dll CS0433-2-lib.dll \
diff --git a/mcs/errors/cs0122-8.cs b/mcs/errors/cs0122-8.cs
new file mode 100644 (file)
index 0000000..5f11502
--- /dev/null
@@ -0,0 +1,11 @@
+// CS0122: `A.AA.Foo()' is inaccessible due to its protection level
+// Line: 16
+// Compiler options: -r:CS0122-8-lib.dll
+
+public class Test
+{
+       public static void Main ()
+       {
+               new B.BB ().Foo ();
+       }
+}
index 2a4bee32c4a43cac8f2848f91dbbf24ea7e5c115..86918b1c7ad2815c0fdaa0fbf58f3af0e48adcb5 100644 (file)
@@ -3442,6 +3442,16 @@ namespace Mono.CSharp {
                                best_candidate_return = best_candidate.ReturnType;
                        }
 
+                       //
+                       // Additional check for possible imported base override method which
+                       // could not be done during IsOverrideMethodBaseTypeAccessible
+                       //
+                       if (best_candidate.IsVirtual && (best_candidate.DeclaringType.Modifiers & Modifiers.PROTECTED) != 0 &&
+                               best_candidate.MemberDefinition.IsImported && !best_candidate.DeclaringType.IsAccessible (ec)) {
+                               ec.Report.SymbolRelatedToPreviousError (best_candidate);
+                               ErrorIsInaccesible (ec, best_candidate.GetSignatureForError (), loc);
+                       }
+
                        return this;
                }
 
index da3e3d7c708b58de7621518b23a541139a05049d..767548d649ba6bcd61ea1e5e64b8e4c91c1562f1 100644 (file)
@@ -390,18 +390,21 @@ namespace Mono.CSharp
                                if ((mod & Modifiers.OVERRIDE) != 0) {
                                        bool is_real_override = false;
                                        if (kind == MemberKind.Method && declaringType.BaseType != null) {
-                                               var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
-                                               var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
-
-                                               //
-                                               // For imported class method do additional validation to be sure that metadata
-                                               // override flag was correct
-                                               // 
-                                               // Difference between protected internal and protected is ok
-                                               //
-                                               const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
-                                               if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) {
-                                                       is_real_override = true;
+                                               var btype = declaringType.BaseType;
+                                               if (IsOverrideMethodBaseTypeAccessible (btype)) {
+                                                       var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
+                                                       var candidate = MemberCache.FindMember (btype, filter, BindingRestriction.None);
+
+                                                       //
+                                                       // For imported class method do additional validation to be sure that metadata
+                                                       // override flag was correct
+                                                       // 
+                                                       // Difference between protected internal and protected is ok
+                                                       //
+                                                       const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
+                                                       if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) {
+                                                               is_real_override = true;
+                                                       }
                                                }
                                        }
 
@@ -434,6 +437,30 @@ namespace Mono.CSharp
                        return ms;
                }
 
+               bool IsOverrideMethodBaseTypeAccessible (TypeSpec baseType)
+               {
+                       switch (baseType.Modifiers & Modifiers.AccessibilityMask) {
+                       case Modifiers.PUBLIC:
+                               return true;
+                       case Modifiers.INTERNAL:
+                               //
+                               // Check whether imported method in base type is accessible from compiled
+                               // context
+                               //
+                               return baseType.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
+                       case Modifiers.PRIVATE:
+                               return false;
+                       default:
+                               // protected
+                               // protected internal
+                               // 
+                               // Method accessibility checks will be done later based on context
+                               // where the method is called (CS0122 error will be reported for inaccessible)
+                               //
+                               return true;
+                       }
+               }
+
                //
                // Imports System.Reflection parameters
                //
diff --git a/mcs/tests/test-846-lib.il b/mcs/tests/test-846-lib.il
new file mode 100644 (file)
index 0000000..ab720ac
--- /dev/null
@@ -0,0 +1,48 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly 'test-846-lib'
+{
+  .hash algorithm 0x00008004
+}
+
+.module 'test-846-lib.dll'
+
+.class private auto ansi beforefieldinit A
+       extends [mscorlib]System.Object
+{
+  .method public hidebysig newslot virtual 
+          instance void  Foo() cil managed
+  {
+    newobj     instance void [mscorlib]System.ApplicationException::.ctor()
+    throw
+  }
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    ldarg.0
+    call       instance void [mscorlib]System.Object::.ctor()
+    ret
+  }
+
+}
+
+.class public auto ansi beforefieldinit B
+       extends A
+{
+  .method public hidebysig virtual instance void 
+          Foo() cil managed
+  {
+    ret
+  }
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    ldarg.0
+    call       instance void A::.ctor()
+    ret
+  }
+}
diff --git a/mcs/tests/test-846.cs b/mcs/tests/test-846.cs
new file mode 100644 (file)
index 0000000..ca53731
--- /dev/null
@@ -0,0 +1,10 @@
+// Compiler options: -r:test-846-lib.dll
+
+class Test
+{
+       public static int Main ()
+       {
+               new B ().Foo ();
+               return 0;
+       }
+}
\ No newline at end of file
index eb0e6faf545c973d23300cb4180834c6c5d9f961..30d8d6b6b0bdd7cb71ef23752f1e07e3e34feec8 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-846.cs">\r
+    <type name="Test">\r
+      <method name="Int32 Main()" attrs="150">\r
+        <size>20</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-85.cs">\r
     <type name="X">\r
       <method name="Int32 Main()" attrs="145">\r