2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / mini / exceptions.cs
index 1db43de32c8599149d00649bb3a2b1643b9ef2f6..0f42f004fc6058c884855dabf1c79f533164300a 100644 (file)
@@ -68,9 +68,25 @@ class Tests {
                return x;
        }
 
+       static int test_0_nested_finally () {
+               int a;
+
+               try {
+                       a = 1;
+               } finally {
+                       try {
+                               a = 2;
+                       } finally {
+                               a = 0;
+                       }
+               }
+               return a;
+       }               
+
        static int test_0_byte_cast () {
                int a;
                long l;
+               ulong ul;
                byte b = 0;
                bool failed;
 
@@ -102,6 +118,7 @@ class Tests {
                if (b != 0)
                        return -2;
 
+
                try {
                        a = 256;
                        failed = true;
@@ -241,7 +258,22 @@ class Tests {
                        return 12;
                if (b != 0)
                        return -12;
-               
+
+               try {
+                       ul = 256;
+                       failed = true;
+                       checked {
+                               b = (byte)ul;
+                       }
+               }
+               catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 13;
+               if (b != 0)
+                       return -13;
+
                return 0;
        }
        
@@ -529,7 +561,7 @@ class Tests {
                if (failed)
                        return 20;
                if (b != 127)
-                       return -19;
+                       return -20;
 
                return 0;
        }
@@ -537,6 +569,7 @@ class Tests {
        static int test_0_ushort_cast () {
                int a;
                long l;
+               ulong ul;
                ushort b;
                bool failed;
 
@@ -684,6 +717,18 @@ class Tests {
                if (failed)
                        return 12;
 
+               try {
+                       ul = 0xfffff;
+                       failed = true;
+                       checked {
+                               b = (ushort)ul;
+                       }
+               } catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 13;
+
                return 0;
        }
        
@@ -886,6 +931,18 @@ class Tests {
                if (failed)
                        return 16;
 
+               try {
+                       l = 0x00000000ffffffff;
+                       failed = true;
+                       checked {
+                               b = (short)l;
+                       }
+               } catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 17;
+
                return 0;
        }
        
@@ -994,6 +1051,41 @@ class Tests {
                if (failed)
                        return 8;
 
+               try {
+                       uint ui = System.UInt32.MaxValue;
+                       failed = true;
+                       checked {
+                               a = (int)ui;
+                       }
+               }
+               catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 9;
+
+               try {
+                       ulong ul = (long)(System.Int32.MaxValue) + 1;
+                       failed = true;
+                       checked {
+                               a = (int)ul;
+                       }
+               }
+               catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 10;
+
+
+               {
+                       int i; 
+                       float f = 1.1f;
+                       checked {
+                               i = (int) f;
+                       }
+               }
+
                return 0;
        }
 
@@ -1097,6 +1189,27 @@ class Tests {
                }
                if (failed)
                        return 8;
+
+               try {
+                       int i = -1;
+                       failed = true;
+                       checked {
+                               a = (uint)i;
+                       }
+               }
+               catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 9;
+
+               {
+                       uint i; 
+                       float f = 1.1f;
+                       checked {
+                               i = (uint) f;
+                       }
+               }
                
                return 0;
        }
@@ -1129,7 +1242,6 @@ class Tests {
                if (failed)
                        return 2;
                
-
                try {
                        double d = System.Int64.MinValue - 1024.0;
                        failed = false;                 
@@ -1154,6 +1266,14 @@ class Tests {
                if (failed)
                        return 4;
 
+               {
+                       long i; 
+                       float f = 1.1f;
+                       checked {
+                               i = (long) f;
+                       }
+               }
+
                return 0;
        }
 
@@ -1161,6 +1281,12 @@ class Tests {
                ulong a;
                bool failed;
 
+               /*
+                * These tests depend on properties of x86 fp arithmetic so they won't work
+                * on other platforms.
+                */
+
+               /*
                try {
                        double d = System.UInt64.MaxValue - 1024.0;
                        failed = true;
@@ -1184,7 +1310,7 @@ class Tests {
                }
                if (failed)
                        return 2;
-               
+               */      
 
                try {
                        double d = 0;
@@ -1210,6 +1336,40 @@ class Tests {
                if (failed)
                        return 4;
 
+               {
+                       ulong i; 
+                       float f = 1.1f;
+                       checked {
+                               i = (ulong) f;
+                       }
+               }
+
+               try {
+                       int i = -1;
+                       failed = true;
+                       checked {
+                               a = (ulong)i;
+                       }
+               }
+               catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 5;
+
+               try {
+                       int i = Int32.MinValue;
+                       failed = true;
+                       checked {
+                               a = (ulong)i;
+                       }
+               }
+               catch (OverflowException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 6;
+
                return 0;
        }
 
@@ -1220,6 +1380,11 @@ class Tests {
                if ((uint)d != 4294967295)
                        return 1;
 
+               /*
+                * These tests depend on properties of x86 fp arithmetic so they won't work
+                * on other platforms.
+                */
+               /*
                d = 0xffffffffffffffff;
 
                if ((ulong)d != 0)
@@ -1230,6 +1395,7 @@ class Tests {
                        
                if ((byte)d != 0)
                        return 4;
+               */
                        
                d = 0xffff;
 
@@ -1266,6 +1432,57 @@ class Tests {
                if (failed)
                        return 2;
 
+               try {
+                       failed = true;
+                       q = -1;
+                       d = Int32.MinValue;
+                       val = d / q;
+               } catch (DivideByZeroException) {
+                       /* wrong exception */
+               } catch (ArithmeticException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 3;
+
+               try {
+                       failed = true;
+                       q = -1;
+                       d = Int32.MinValue;
+                       val = d % q;
+               } catch (DivideByZeroException) {
+                       /* wrong exception */
+               } catch (ArithmeticException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 4;
+
+               return 0;
+       }
+
+       static int return_55 () {
+               return 55;
+       }
+
+       static int test_0_cfold_div_zero () {
+               // Test that constant folding doesn't cause division by zero exceptions
+               if (return_55 () != return_55 ()) {
+                       int d = 1;
+                       int q = 0;
+                       int val;                        
+
+                       val = d / q;
+                       val = d % q;
+
+                       q = -1;
+                       d = Int32.MinValue;
+                       val = d / q;
+
+                       q = -1;
+                       val = d % q;
+               }
+
                return 0;
        }
 
@@ -1320,6 +1537,32 @@ class Tests {
                if (failed)
                        return 2;
 
+               try {
+                       failed = true;
+                       q = -1;
+                       d = Int64.MinValue;
+                       val = d / q;
+               } catch (DivideByZeroException) {
+                       /* wrong exception */
+               } catch (ArithmeticException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 3;
+
+               try {
+                       failed = true;
+                       q = -1;
+                       d = Int64.MinValue;
+                       val = d % q;
+               } catch (DivideByZeroException) {
+                       /* wrong exception */
+               } catch (ArithmeticException) {
+                       failed = false;
+               }
+               if (failed)
+                       return 4;
+
                return 0;
        }
 
@@ -1394,6 +1637,22 @@ class Tests {
                return res;
        }
 
+       // Test that double[] can't be cast to double (bug #46027)
+       static int test_0_invalid_unbox_arrays () {
+               double[] d1 = { 1.0 };
+               double[][] d2 = { d1 };
+               Array a = d2;
+
+               try {
+                       foreach (double d in a) {
+                       }
+                       return 1;
+               }
+               catch (InvalidCastException e) {
+                       return 0;
+               }
+       }
+
        /* bug# 42190, at least mcs generates a leave for the return that
         * jumps out of multiple exception clauses: we used to execute just 
         * one enclosing finally block.
@@ -1489,5 +1748,455 @@ class Tests {
                        return 0;
                return 200;
        }
+
+       static void helper_out_obj (out object o) {
+               o = (object)"buddy";
+       }
+
+       static void helper_out_string (out string o) {
+               o = "buddy";
+       }
+
+       static int test_2_array_mismatch () {
+               string[] a = { "hello", "world" };
+               object[] b = a;
+               bool passed = false;
+
+               try {
+                       helper_out_obj (out b [1]);
+               } catch (ArrayTypeMismatchException) {
+                       passed = true;
+               }
+               if (!passed)
+                       return 0;
+               helper_out_string (out a [1]);
+               if (a [1] != "buddy")
+                       return 1;
+               return 2;
+       }
+
+       static int test_0_ovf () {
+               int ocount = 0;
+               
+               checked {
+
+                       ocount = 0;
+                       try {
+                               ulong a =  UInt64.MaxValue - 1;
+                               ulong t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 1;
+
+                       ocount = 0;
+                       try {
+                               ulong a =  UInt64.MaxValue;
+                               ulong t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 2;
+
+                       ocount = 0;
+                       try {
+                               long a = Int64.MaxValue - 1;
+                               long t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 3;
+
+                       try {
+                               long a = Int64.MaxValue;
+                               long t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 4;
+
+                       ocount = 0;
+                       try {
+                               ulong a = UInt64.MaxValue - 1;
+                               ulong t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 5;
+
+                       try {
+                               ulong a = UInt64.MaxValue;
+                               ulong t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 6;
+
+                       ocount = 0;
+                       try {
+                               long a = Int64.MinValue + 1;
+                               long t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 7;
+
+                       ocount = 0;
+                       try {
+                               long a = Int64.MinValue;
+                               long t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 8;
+
+                       ocount = 0;
+                       try {
+                               ulong a = UInt64.MinValue + 1;
+                               ulong t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 9;
+
+                       ocount = 0;
+                       try {
+                               ulong a = UInt64.MinValue;
+                               ulong t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 10;
+
+                       ocount = 0;
+                       try {
+                               int a = Int32.MinValue + 1;
+                               int t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 11;
+
+                       ocount = 0;
+                       try {
+                               int a = Int32.MinValue;
+                               int t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 12;
+
+                       ocount = 0;
+                       try {
+                               uint a = 1;
+                               uint t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 13;
+
+                       ocount = 0;
+                       try {
+                               uint a = 0;
+                               uint t = a--;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 14;
+
+                       ocount = 0;
+                       try {
+                               sbyte a = 126;
+                               sbyte t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 15;
+
+                       ocount = 0;
+                       try {
+                               sbyte a = 127;
+                               sbyte t = a++;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 16;
+
+                       ocount = 0;
+                       try {
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 17;
+
+                       ocount = 0;
+                       try {
+                               int a = 1 << 29;
+                               int t = a*2;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 18;
+
+                       ocount = 0;
+                       try {
+                               int a = 1 << 30;
+                               int t = a*2;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 19;
+
+                       ocount = 0;
+                       try {
+                               ulong a = 0xffffffffff;
+                               ulong t = a*0x0ffffff;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 0)
+                               return 20;
+
+                       ocount = 0;
+                       try {
+                               ulong a = 0xffffffffff;
+                               ulong t = a*0x0fffffff;
+                       } catch {
+                               ocount++;
+                       }
+                       if (ocount != 1)
+                               return 21;
+
+                       ocount = 0;
+                       try {
+                               long a = Int64.MinValue;
+                               long b = 10;
+                               long v = a * b;
+                       } catch {
+                               ocount ++;
+                       }
+                       if (ocount != 1)
+                               return 22;
+
+                       ocount = 0;
+                       try {
+                               long a = 10;
+                               long b = Int64.MinValue;
+                               long v = a * b;
+                       } catch {
+                               ocount ++;
+                       }
+                       if (ocount != 1)
+                               return 23;
+               }
+               
+               return 0;
+       }
+
+       class Broken {
+               static int i;
+
+               static Broken () {
+                       throw new Exception ("Ugh!");
+               }
+       
+               public static int DoSomething () {
+                       return i;
+               }
+       }
+
+       static int test_0_exception_in_cctor () {
+               try {
+                       Broken.DoSomething ();
+               }
+               catch (TypeInitializationException) {
+                       // This will only happen once even if --regression is used
+               }
+               return 0;
+       }
+
+       static int test_5_regalloc () {
+               int i = 0;
+
+               try {
+                       for (i = 0; i < 10; ++i) {
+                               if (i == 5)
+                                       throw new Exception ();
+                       }
+               }
+               catch (Exception) {
+                       if (i != 5)
+                               return i;
+               }
+
+               // Check that variables written in catch clauses are volatile
+               int j = 0;
+               try {
+                       throw new Exception ();
+               }
+               catch (Exception) {
+                       j = 5;
+               }
+               if (j != 5)
+                       return 6;
+
+               int k = 0;
+               try {
+                       try {
+                               throw new Exception ();
+                       }
+                       finally {
+                               k = 5;
+                       }
+               }
+               catch (Exception) {
+               }
+               if (k != 5)
+                       return 7;
+
+               return i;
+       }
+
+       /* MarshalByRefObject prevents the methods from being inlined */
+       class ThrowClass : MarshalByRefObject {
+               public static void rethrow1 () {
+                       throw new Exception ();
+               }
+
+               public static void rethrow2 () {
+                       rethrow1 ();
+               }
+       }
+
+       static int test_0_rethrow_stacktrace () {
+               // Check that rethrowing an exception preserves the original stack trace
+               try {
+                       try {
+                               ThrowClass.rethrow2 ();
+                       }
+                       catch (Exception ex) {
+                               // Check that each catch clause has its own exception variable
+                               // If not, the throw below will overwrite the exception used
+                               // by the rethrow
+                               try {
+                                       throw new DivideByZeroException ();
+                               }
+                               catch (Exception foo) {
+                               }
+
+                               throw;
+                       }
+               }
+               catch (Exception ex) {
+                       if (ex.StackTrace.IndexOf ("rethrow2") != -1)
+                               return 0;
+               }
+
+               return 1;
+       }
+       
+       interface IFace {}
+       class Face : IFace {}
+               
+       static int test_1_array_mismatch_2 () {
+               try {
+                       object [] o = new Face [1];
+                       o [0] = 1;
+                       return 0;
+               } catch (ArrayTypeMismatchException) {
+                       return 1;
+               }
+       }
+       
+       static int test_1_array_mismatch_3 () {
+               try {
+                       object [] o = new IFace [1];
+                       o [0] = 1;
+                       return 0;
+               } catch (ArrayTypeMismatchException) {
+                       return 1;
+               }
+       }
+       
+       static int test_1_array_mismatch_4 () {
+               try {
+                       object [][] o = new Face [5] [];
+                       o [0] = new object [5];
+                       
+                       return 0;
+               } catch (ArrayTypeMismatchException) {
+                       return 1;
+               }
+       }
+
+       static int test_0_array_size () {
+               bool failed;
+
+               try {
+                       failed = true;
+                       int[] mem1 = new int [Int32.MaxValue];
+               }
+               catch (OutOfMemoryException e) {
+                       failed = false;
+               }
+               if (failed)
+                       return 1;
+
+               try {
+                       failed = true;
+                       int[,] mem2 = new int [Int32.MaxValue, Int32.MaxValue];
+               }
+               catch (OutOfMemoryException e) {
+                       failed = false;
+               }
+               if (failed)
+                       return 2;
+
+               return 0;
+       }
+
+       struct S {
+               int i, j, k, l, m, n;
+       }
+
+       static IntPtr[] addr;
+
+       static unsafe void throw_func (int i, S s) {
+               addr [i] = new IntPtr (&i);
+               throw new Exception ();
+       }
+
+       /* Test that arguments are correctly popped off the stack during unwinding */
+       static int test_0_stack_unwind () {
+               addr = new IntPtr [1000];
+               S s = new S ();
+               for (int j = 0; j < 1000; j++) {
+                       try {
+                               throw_func (j, s);
+                       }
+                       catch (Exception) {
+                       }
+               }
+               return (addr [0].ToInt64 () - addr [100].ToInt64 () < 100) ? 0 : 1;
+       }               
 }