2008-05-01 Rodrigo Kumpera <rkumpera@novell.com>
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 1 May 2008 20:33:03 +0000 (20:33 -0000)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 1 May 2008 20:33:03 +0000 (20:33 -0000)
* unverifiable_ldsfld_no_fld.il: Fixed compilation
and renamed to invalid_ldsfld_no_fld.il.

* BatchCompiler.cs: New driver to fast compile the
verifier test suite. It's about 20x faster now.

* Makefile: Use the ilasm driver for faster compilation.

svn path=/trunk/mono/; revision=102299

136 files changed:
LICENSE
eglib/ChangeLog
eglib/src/glib.h
eglib/src/gutf8.c
eglib/test/utf8.c
mcs/class/Managed.Windows.Forms/System.Windows.Forms.Theming/VisualStyles/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms.Theming/VisualStyles/TabControlPainter.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridView.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewCell.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewCheckBoxCell.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewCheckBoxColumn.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewColumnDesignTimeVisibleAttribute.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewColumnHeaderCell.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewElement.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewRow.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewRowCollection.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewTextBoxCell.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/InputLanguageCollection.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripDropDownItem.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs
mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/DataGridViewCellTest.cs
mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/DataGridViewRowCollectionTest.cs
mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/DataGridViewRowTest.cs
mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/InputLanguageTest.cs
mcs/class/System.Core/ChangeLog
mcs/class/System.Core/System.Core-2008.csproj
mcs/class/System.Core/System.Core.dll.sources
mcs/class/System.Core/System.Linq/AOrderedEnumerable.cs [deleted file]
mcs/class/System.Core/System.Linq/ChangeLog
mcs/class/System.Core/System.Linq/Enumerable.cs
mcs/class/System.Core/System.Linq/InternalOrderedSequence.cs [deleted file]
mcs/class/System.Core/System.Linq/OrderedEnumerable.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/OrderedSequence.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/QuickSort.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/SortContext.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/SortDirection.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/SortSequenceContext.cs [new file with mode: 0644]
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Convert.cs
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Utils.cs
mcs/class/System.Core/Test/System.Linq/ChangeLog
mcs/class/System.Core/Test/System.Linq/EnumerableTest.cs
mcs/class/System.Core/Test/System.Linq/QueryableProviderTest.cs
mcs/class/System.Web/System.Web.UI.WebControls/ChangeLog
mcs/class/System.Web/System.Web.UI.WebControls/SiteMapDataSource.cs
mcs/class/System.Web/System.Web/ChangeLog
mcs/class/System.Web/System.Web/HttpApplication.cs
mcs/class/System.Web/System.Web/SiteMapNode.cs
mcs/class/System.Xml.Linq/System.Xml.Linq/ChangeLog
mcs/class/System.Xml.Linq/System.Xml.Linq/XElement.cs
mcs/class/System.Xml.Linq/System.Xml.Linq/XNode.cs
mcs/class/System.Xml.Linq/Test/System.Xml.Linq/ChangeLog
mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XNodeReaderTest.cs
mcs/class/System/Microsoft.VisualBasic/ChangeLog
mcs/class/System/Microsoft.VisualBasic/VBCodeGenerator.cs
mcs/class/System/System.Net/ChangeLog
mcs/class/System/System.Net/WebPermission.cs
mcs/class/System/Test/Microsoft.VisualBasic/ChangeLog
mcs/class/System/Test/Microsoft.VisualBasic/CodeGeneratorFromTypeTest.cs
mcs/class/System/Test/System.CodeDom.Compiler/ChangeLog
mcs/class/System/Test/System.CodeDom.Compiler/ExecutorTest.cs
mcs/class/System/Test/System.ComponentModel/ChangeLog
mcs/class/System/Test/System.ComponentModel/ComponentConverterTests.cs
mcs/class/corlib/ChangeLog
mcs/class/corlib/System.Reflection.Emit/ChangeLog
mcs/class/corlib/System.Reflection.Emit/ConstructorBuilder.cs
mcs/class/corlib/System.Reflection.Emit/ConstructorOnTypeBuilderInst.cs
mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs
mcs/class/corlib/System.Reflection.Emit/TypeBuilder.cs
mcs/class/corlib/System.Reflection/ChangeLog
mcs/class/corlib/System.Reflection/ParameterInfo.cs
mcs/class/corlib/System.Security.Cryptography/ChangeLog
mcs/class/corlib/System.Security.Cryptography/SHA1CryptoServiceProvider.cs
mcs/class/corlib/System.Security.Cryptography/SHA256Managed.cs
mcs/class/corlib/System.Security.Cryptography/SHA384Managed.cs
mcs/class/corlib/Test/System.Collections.Generic/ChangeLog
mcs/class/corlib/Test/System.Collections.Generic/DictionaryTest.cs
mcs/class/corlib/Test/System.IO/ChangeLog
mcs/class/corlib/Test/System.IO/DirectoryTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/ChangeLog
mcs/class/corlib/Test/System.Reflection.Emit/ConstructorBuilderTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/ConstructorOnTypeBuilderInstTest.cs [new file with mode: 0644]
mcs/class/corlib/Test/System.Reflection.Emit/MethodOnTypeBuilderInstTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/TypeBuilderTest.cs
mcs/class/corlib/corlib_test.dll.sources
mcs/errors/gcs0831-2.cs [new file with mode: 0644]
mcs/errors/gcs0831-3.cs [new file with mode: 0644]
mcs/errors/gcs0831.cs [new file with mode: 0644]
mcs/errors/gcs0832-4.cs [new file with mode: 0644]
mcs/errors/gcs0843.cs [new file with mode: 0644]
mcs/errors/gcs0845.cs [new file with mode: 0644]
mcs/errors/gcs1944-2.cs [new file with mode: 0644]
mcs/errors/gcs1944-3.cs [new file with mode: 0644]
mcs/errors/gcs1944-4.cs [new file with mode: 0644]
mcs/errors/gcs1944-5.cs [new file with mode: 0644]
mcs/errors/gcs1944-6.cs [new file with mode: 0644]
mcs/errors/gcs1944-7.cs [new file with mode: 0644]
mcs/errors/gcs1944.cs [new file with mode: 0644]
mcs/errors/gcs1945.cs [new file with mode: 0644]
mcs/errors/gcs1953.cs [new file with mode: 0644]
mcs/mcs/ChangeLog
mcs/mcs/anonymous.cs
mcs/mcs/assign.cs
mcs/mcs/attribute.cs
mcs/mcs/class.cs
mcs/mcs/constant.cs
mcs/mcs/doc.cs
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/flowanalysis.cs
mcs/mcs/iterators.cs
mcs/mcs/lambda.cs
mcs/mcs/linq.cs
mcs/mcs/literal.cs
mcs/mcs/modifiers.cs
mcs/mcs/nullable.cs
mcs/mcs/statement.cs
mcs/mcs/typemanager.cs
mcs/tests/gtest-391.cs [new file with mode: 0644]
mcs/tests/gtest-etree-01.cs
mcs/tests/gtest-etree-07.cs
mcs/tests/test-641.cs [new file with mode: 0644]
mcs/tests/ver-il-gmcs.xml
mono/metadata/ChangeLog
mono/metadata/process.c
mono/metadata/sgen-gc.c
mono/metadata/verify.c
mono/tests/verifier/BatchCompiler.cs [new file with mode: 0644]
mono/tests/verifier/ChangeLog
mono/tests/verifier/Makefile
mono/tests/verifier/invalid_ldsfld_no_fld.il [new file with mode: 0644]
mono/tests/verifier/make_il_overflow_test.sh [new file with mode: 0755]
mono/tests/verifier/make_tests.sh
mono/tests/verifier/unverifiable_ldsfld_no_fld.il [deleted file]

diff --git a/LICENSE b/LICENSE
index 724330960ab347deb085b03230fcbb4e30390082..af6f96030c8b65da5d1bd6187abacb35f955768b 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -101,6 +101,10 @@ For comments, corrections and updates, please contact mono@novell.com
 
        Manual pages and Mono documentation are covered by the MIT X11 license. 
 
+* samples
+
+       The code in the "samples" directory is released under the MIT X11 license.
+
 * The Licenses
 
        These are the licenses used in Mono, the files are located:
index cbea05269d2426bcaf17c4d0610df8f6ee49b423..27fbee764f4e9eacb84d7a62df6a4ea7a4f5c0aa 100644 (file)
@@ -1,9 +1,19 @@
+2008-05-01  Bill Holmes  <billholmes54@gmail.com>
+
+       * src/glib.h : Adding declarations for g_ucs4_to_utf16 and g_utf16_to_ucs4.
+
+       * src/gutf8.c : Adding implementation for g_ucs4_to_utf16 and g_utf16_to_ucs4.
+
+       * test/utf8.c Adding tests for g_ucs4_to_utf16 and g_utf16_to_ucs4.
+
+       Contributed under MIT/X11 license.
+
 2008-04-20  Geoff Norton  <gnorton@novell.com>
 
        * src/gspan.c: Fix the _NSGetEnviron define to prevent an impropoer
        pointer dereference.
 
-2007-03-19  Bill Holmes  <billholmes54@gmail.com>
+2008-03-19  Bill Holmes  <billholmes54@gmail.com>
 
        * src/gpath.c (g_path_is_absolute) : Adding a case for '/'
          on Windows.
index b47b8d7dcf827c3f818ca1e226a39a4dfc59d067..77791d31283c87a372fca1ed1fa9d97280edbdf6 100644 (file)
@@ -562,6 +562,8 @@ typedef enum {
 
 gunichar2 *g_utf8_to_utf16 (const gchar *str, glong len, glong *items_read, glong *items_written, GError **error);
 gchar     *g_utf16_to_utf8 (const gunichar2 *str, glong len, glong *items_read, glong *items_written, GError **error);
+gunichar2 *g_ucs4_to_utf16 (const gunichar *str, glong len, glong *items_read, glong *items_written, GError **error);
+gunichar  *g_utf16_to_ucs4 (const gunichar2 *str, glong len, glong *items_read, glong *items_written, GError **error);
 
 #define u8to16(str) g_utf8_to_utf16(str, (glong)strlen(str), NULL, NULL, NULL)
 
index c4c3d7ddef84a62762f358808976c1d217c2e593..77de844693d045222c4f479eeb5b401db48de1ec 100644 (file)
@@ -380,18 +380,170 @@ utf16_to_utf8_len (const gunichar2 *str, glong len, glong *items_read, GError **
        return ret;
 }
 
+static glong
+g_ucs4_to_utf16_len (const gunichar *str, glong len, glong *items_read, GError **error)
+{
+       glong retlen = 0;
+       glong errindex = 0;
+       const gunichar *lstr = str;
+
+       if (!str)
+               return 0;
+
+       while (*lstr != '\0' && len--) {
+               gunichar ch;
+               ch = *lstr++;
+               if (ch <= 0x0000FFFF) { 
+                       if (ch >= 0xD800 && ch <= 0xDFFF) {
+                               errindex = (glong)(lstr - str)-1;
+                               if (error)
+                                       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                                       "Invalid sequence in conversion input");
+                               if (items_read)
+                                       *items_read = errindex;
+                               return 0;
+                       } else {
+                               retlen++;
+                       }
+               } else if (ch > 0x10FFFF) {
+                       errindex = (glong)(lstr - str)-1;
+                       if (error)
+                               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                               "Character out of range for UTF-16");
+                       if (items_read)
+                               *items_read = errindex;
+                       return 0;
+
+               } else {
+                       retlen+=2;
+               }
+       }
+
+       if (items_read)
+               *items_read = (glong)(lstr - str);
+       return retlen;
+}
+
 gunichar2*
 g_ucs4_to_utf16 (const gunichar *str, glong len, glong *items_read, glong *items_written, GError **error)
 {
-       g_assert_not_reached ();
+       glong allocsz;
+       gunichar2 *retstr = 0;
+       gunichar2 *retch = 0;
+       glong nwritten = 0;
+       GError *lerror =0 ;
+
+       allocsz = g_ucs4_to_utf16_len (str, len, items_read, &lerror);
+
+       if (!lerror) {
+               retch = retstr = g_malloc ((allocsz+1) * sizeof (gunichar2));
+               retstr[allocsz] = '\0';
+
+               while (*str != '\0' && len--) {
+                       gunichar ch;
+                       ch = *str++;
+                       if (ch <= 0x0000FFFF && (ch < 0xD800 || ch > 0xDFFF)) {
+                               *retch++ = (gunichar2)ch;
+                               nwritten ++;
+                       } else {
+                               ch -= 0x0010000UL;
+                               *retch++ = (gunichar2)((ch >> 10) + 0xD800);
+                               *retch++ = (gunichar2)((ch & 0x3FFUL) + 0xDC00);
+                               nwritten +=2;
+                       }
+               }
+       }
+
+       if (items_written)
+               *items_written = nwritten;
+       if (error)
+               *error = lerror;
+
+       return retstr;
+}
+
+static glong
+g_utf16_to_ucs4_len (const gunichar2 *str, glong len, glong *items_read, GError **error)
+{
+       glong retlen = 0;
+       glong errindex = 0;
+       const gunichar2 *lstr = str;
+       gunichar2 ch,ch2;
 
-       return NULL;
+       if (!str)
+               return 0;
+
+       while (*lstr != '\0' && len--) {
+               ch = *lstr++;
+               if (ch >= 0xD800 && ch <= 0xDBFF) {
+                       if (!len--) {
+                               lstr--;
+                               break;
+                       }
+                       ch2 = *lstr;
+                       if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
+                               lstr++;
+                       } else {
+                               errindex = (glong)(lstr - str);
+                               if (error)
+                                       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                                       "Invalid sequence in conversion input");
+                               if (items_read)
+                                       *items_read = errindex;
+                               return 0;
+                       }
+               } else {
+                       if (ch >= 0xDC00 && ch <= 0xDFFF) {
+                               errindex = (glong)(lstr - str)-1;
+                               if (error)
+                                       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                                       "Invalid sequence in conversion input");
+                               if (items_read)
+                                       *items_read = errindex;
+                               return 0;
+                       }
+               }
+               retlen++;
+       }
+
+       if (items_read)
+               *items_read = (glong)(lstr - str);
+
+       return retlen;
 }
 
 gunichar*
 g_utf16_to_ucs4 (const gunichar2 *str, glong len, glong *items_read, glong *items_written, GError **error)
 {
-       g_assert_not_reached ();
+       glong allocsz;
+       gunichar *retstr = 0;
+       gunichar *retch = 0;
+       glong nwritten = 0;
+       GError *lerror =0 ;
+       gunichar ch,ch2;
+
+       allocsz = g_utf16_to_ucs4_len (str, len, items_read, &lerror);
+
+       if (!lerror) {
+               retch = retstr = g_malloc ((allocsz+1) * sizeof (gunichar));
+               retstr[allocsz] = '\0';
+               nwritten = allocsz;
+
+               while (*str != '\0' && allocsz--) {
+                       ch = *str++;
+                       if (ch >= 0xD800 && ch <= 0xDBFF) {
+                               ch2 = *str++;
+                               ch = ((ch - (gunichar)0xD800) << 10)
+                                     + (ch2 - (gunichar)0xDC00) + (gunichar)0x0010000UL;
+                       }
+                       *retch++ = ch;
+               }
+       }
+
+       if (items_written)
+               *items_written = nwritten;
+       if (error)
+               *error = lerror;
 
-       return NULL;
+       return retstr;
 }
index 4076cc8ca558ffadfe29e47e2d005887bf2a42bc..f12bb5f44172d2afdcb38e2fdf54d7dcb06e9bd9 100644 (file)
@@ -269,6 +269,221 @@ test_xdigit ()
                return OK;
 }
 
+static RESULT
+ucs4_to_utf16_check_result (const gunichar2 *result_str, const gunichar2 *expected_str,
+                           glong result_items_read, glong expected_items_read,
+                           glong result_items_written, glong expected_items_written,
+                           GError* result_error, gboolean expect_error)
+{
+       glong i;
+       if (result_items_read != expected_items_read)
+               return FAILED("Incorrect number of items read %d", result_items_read);
+       if (result_items_written != expected_items_written)
+               return FAILED("Incorrect number of items written %d", result_items_written);
+       if (result_error && !expect_error)
+               return FAILED("There should not be an error code.");
+       if (!result_error && expect_error)
+               return FAILED("Unexpected error object.");
+       if (expect_error && result_str)
+               return FAILED("NULL should be returned when an error occurs.");
+       if (!expect_error && !result_str)
+               return FAILED("When no error occurs NULL should not be returned.");
+       for (i=0; i<expected_items_written;i++) {
+               if (result_str [i] != expected_str [i])
+                       return FAILED("Incorrect value %d at index %d", result_str [i], i);
+       }
+       if (result_str && result_str[expected_items_written] != '\0') 
+               return FAILED("Null termination not found at the end of the string.");
+       
+       return OK;
+}
+
+RESULT
+test_ucs4_to_utf16 ()
+{
+       static gunichar str1[12] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'};
+       static gunichar2 exp1[12] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'};
+       static gunichar str2[3] = {'h',0x80000000,'\0'};
+       static gunichar2 exp2[2] = {'h','\0'};
+       static gunichar str3[3] = {'h',0xDA00,'\0'};
+       static gunichar str4[3] = {'h',0x10FFFF,'\0'};
+       static gunichar2 exp4[4] = {'h',0xdbff,0xdfff,'\0'};
+       static gunichar str5[7] = {0xD7FF,0xD800,0xDFFF,0xE000,0x110000,0x10FFFF,'\0'};
+       static gunichar2 exp5[5] = {0xD7FF,0xE000,0xdbff,0xdfff,'\0'};
+       static glong read_write[12] = {1,1,0,0,0,0,1,1,0,0,1,2};
+       gunichar2* res;
+       glong items_read, items_written, current_write_index;
+       GError* err=0;
+       RESULT check_result;
+       glong i;
+       
+       res = g_ucs4_to_utf16 (str1, 12, &items_read, &items_written, &err);
+       check_result = ucs4_to_utf16_check_result (res, exp1, items_read, 11, items_written, 11, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_ucs4_to_utf16 (str2, 0, &items_read, &items_written, &err);
+       check_result = ucs4_to_utf16_check_result (res, exp2, items_read, 0, items_written, 0, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_ucs4_to_utf16 (str2, 1, &items_read, &items_written, &err);
+       check_result = ucs4_to_utf16_check_result (res, exp2, items_read, 1, items_written, 1, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_ucs4_to_utf16 (str2, 2, &items_read, &items_written, &err);
+       check_result = ucs4_to_utf16_check_result (res, 0, items_read, 1, items_written, 0, err, TRUE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       err = 0;
+       res = g_ucs4_to_utf16 (str3, 2, &items_read, &items_written, &err);
+       check_result = ucs4_to_utf16_check_result (res, 0, items_read, 1, items_written, 0, err, TRUE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       err = 0;
+       res = g_ucs4_to_utf16 (str4, 5, &items_read, &items_written, &err);
+       check_result = ucs4_to_utf16_check_result (res, exp4, items_read, 2, items_written, 3, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       // This loop tests the bounds of the conversion algorithm
+       current_write_index = 0;
+       for (i=0;i<6;i++) {
+               items_read = items_written = 0;
+               err = 0;
+               res = g_ucs4_to_utf16 (&str5[i], 1, &items_read, &items_written, &err);
+               check_result = ucs4_to_utf16_check_result (res, &exp5[current_write_index], 
+                                       items_read, read_write[i*2], items_written, read_write[(i*2)+1], err, !read_write[(i*2)+1]);
+               if (check_result) return check_result;
+               g_free (res);
+               current_write_index += items_written;
+       }
+
+       return OK;
+}
+
+static RESULT
+utf16_to_ucs4_check_result (const gunichar *result_str, const gunichar *expected_str,
+                           glong result_items_read, glong expected_items_read,
+                           glong result_items_written, glong expected_items_written,
+                           GError* result_error, gboolean expect_error)
+{
+       glong i;
+       if (result_items_read != expected_items_read)
+               return FAILED("Incorrect number of items read %d", result_items_read);
+       if (result_items_written != expected_items_written)
+               return FAILED("Incorrect number of items written %d", result_items_written);
+       if (result_error && !expect_error)
+               return FAILED("There should not be an error code.");
+       if (!result_error && expect_error)
+               return FAILED("Unexpected error object.");
+       if (expect_error && result_str)
+               return FAILED("NULL should be returned when an error occurs.");
+       if (!expect_error && !result_str)
+               return FAILED("When no error occurs NULL should not be returned.");
+       for (i=0; i<expected_items_written;i++) {
+               if (result_str [i] != expected_str [i])
+                       return FAILED("Incorrect value %d at index %d", result_str [i], i);
+       }
+       if (result_str && result_str[expected_items_written] != '\0') 
+               return FAILED("Null termination not found at the end of the string.");
+       
+       return OK;
+}
+
+RESULT
+test_utf16_to_ucs4 ()
+{
+       static gunichar2 str1[12] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'};
+       static gunichar exp1[12] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'};
+       static gunichar2 str2[7] = {'H', 0xD800, 0xDC01,0xD800,0xDBFF,'l','\0'};
+       static gunichar exp2[3] = {'H',0x00010001,'\0'};
+       static gunichar2 str3[4] = {'H', 0xDC00 ,'l','\0'};
+       static gunichar exp3[2] = {'H','\0'};
+       static gunichar2 str4[20] = {0xDC00,0xDFFF,0xDFF,0xD800,0xDBFF,0xD800,0xDC00,0xD800,0xDFFF,
+                                    0xD800,0xE000,0xDBFF,0xDBFF,0xDBFF,0xDC00,0xDBFF,0xDFFF,0xDBFF,0xE000,'\0'};
+       static gunichar exp4[6] = {0xDFF,0x10000,0x103ff,0x10fc00,0x10FFFF,'\0'};
+       static glong read_write[33] = {1,0,0,1,0,0,1,1,1,2,1,0,2,2,1,2,2,1,2,1,0,2,1,0,2,2,1,2,2,1,2,1,0};
+       gunichar* res;
+       glong items_read, items_written, current_read_index,current_write_index;
+       GError* err=0;
+       RESULT check_result;
+       glong i;
+       
+       res = g_utf16_to_ucs4 (str1, 12, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp1, items_read, 11, items_written, 11, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_utf16_to_ucs4 (str2, 0, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp2, items_read, 0, items_written, 0, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_utf16_to_ucs4 (str2, 1, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp2, items_read, 1, items_written, 1, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+       
+       items_read = items_written = 0;
+       res = g_utf16_to_ucs4 (str2, 2, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp2, items_read, 1, items_written, 1, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_utf16_to_ucs4 (str2, 3, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp2, items_read, 3, items_written, 2, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_utf16_to_ucs4 (str2, 4, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp2, items_read, 3, items_written, 2, err, FALSE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       res = g_utf16_to_ucs4 (str2, 5, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp2, items_read, 4, items_written, 0, err, TRUE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       items_read = items_written = 0;
+       err = 0;
+       res = g_utf16_to_ucs4 (str3, 5, &items_read, &items_written, &err);
+       check_result = utf16_to_ucs4_check_result (res, exp3, items_read, 1, items_written, 0, err, TRUE);
+       if (check_result) return check_result;
+       g_free (res);
+
+       // This loop tests the bounds of the conversion algorithm
+       current_read_index = current_write_index = 0;
+       for (i=0;i<11;i++) {
+               items_read = items_written = 0;
+               err = 0;
+               res = g_utf16_to_ucs4 (&str4[current_read_index], read_write[i*3], &items_read, &items_written, &err);
+               check_result = utf16_to_ucs4_check_result (res, &exp4[current_write_index], items_read, 
+                                            read_write[(i*3)+1], items_written, read_write[(i*3)+2], err, 
+                                            !read_write[(i*3)+2]);
+               if (check_result) return check_result;
+               g_free (res);
+               current_read_index += read_write[i*3];
+               current_write_index += items_written;
+       }
+
+       return OK;
+}
+
 /*
  * test initialization
  */
@@ -279,6 +494,8 @@ static Test utf8_tests [] = {
        {"g_utf8_seq", test_utf8_seq},
        {"g_convert", test_convert },
        {"g_unichar_xdigit_value", test_xdigit },
+       {"g_ucs4_to_utf16", test_ucs4_to_utf16 },
+       {"g_utf16_to_ucs4", test_utf16_to_ucs4 },
        {NULL, NULL}
 };
 
index 4900a01bc1258a8322abf626ce2dfef465e15137..ffe7ef0ae2c7b1e3d6f66ec480e36ef7fb8cd8e0 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-30  George Giolfan  <georgegiolfan@yahoo.com>
+
+       * TabControlPainter.cs: Ordered usings.
+
 2008-04-28  George Giolfan  <georgegiolfan@yahoo.com>
 
        * TabControlPainter.cs: Fixed duplication.
index 76cfe6d2dc84b3e79584652f01e5dcb142352d91..f082ea2f8410e4f37cc4dfabe715c1722b8f79e4 100644 (file)
@@ -22,8 +22,8 @@
 // Authors:
 //     George Giolfan (georgegiolfan@yahoo.com)
 
-using System.Windows.Forms.VisualStyles;
 using System.Drawing;
+using System.Windows.Forms.VisualStyles;
 namespace System.Windows.Forms.Theming.VisualStyles
 {
        class TabControlPainter : Default.TabControlPainter
index d5b7b55088cc6647ccfaf62e2d8400e51bf0d0cb..62864598577eaf9436fed8c4db49ac857d73a60d 100644 (file)
@@ -1,3 +1,44 @@
+2008-05-01  Jonathan Pobst  <monkey@jpobst.com>
+
+       * InputLanguageCollection.cs: Implement the collection better.
+       [Fixes bug #385506]
+
+2008-05-01  Jonathan Pobst  <monkey@jpobst.com>
+
+       * ToolStripDropDownItem.cs: Get the correct event object for
+       DropDownItemClicked.
+       * ToolStripMenuItem.cs: Raise DropDownItemClicked on our owner.
+       [Fixes bug #385475]
+
+2008-05-01  Jonathan Pobst  <monkey@jpobst.com>
+
+       * DataGridViewRowCollection.cs: We don't currently support shared 
+       rows.  Should fix test failures caused by previous commit.
+
+2008-04-30  Jonathan Pobst  <monkey@jpobst.com>
+
+       * DataGridViewRow.cs: Fixes for cloning the row, ensure header cell's
+       datagridview gets set.  Only paint cells in visible columns.
+       * DataGridViewCell.cs: Draw border after cell content.
+       * DataGridView.cs: Invalidate after setting some properties.  Only
+       use visible columns.  Fit hit test bug with areas in the col/row header
+       area but not in a row or col.  Implement UpdateCell/Row methods.
+
+2008-04-30  Jonathan Pobst  <monkey@jpobst.com>
+
+       * DataGridViewElement.cs: Don't throw NIEX.
+       * DataGridViewColumnHeaderCell.cs: Draw error icons for top left header cells.
+       * DataGridViewColumnDesignTimeVisibleAttribute.cs: Don't throw NIEX.
+       * DataGridViewCheckBoxColumn.cs: Implement ToString.
+       * DataGridViewCheckBoxCell.cs: Allow DBNull as a value.
+       * DataGridViewCell.cs: Don't raise CellFormatting for RowHeader cells,
+       if the user filled in the formatting Value, use it.
+
+2008-04-30  Jonathan Pobst  <monkey@jpobst.com>
+
+       * DataGridViewTextBoxCell.cs: Fix for objects that cannot be cast
+       to a string.
+
 2008-04-29  Carlos Alberto Cortez <calberto.cortez@gmail.com>
 
        * BindingSource.cs: Some corrections to Filter property, as well as
index d44cccc9853cc233b7137707cea0e0dbaed7c196..1aa1900bc4bb593037d58a67368ad335a578f94e 100644 (file)
@@ -255,6 +255,7 @@ namespace System.Windows.Forms {
                                        allowUserToAddRows = value;
                                        OnAllowUserToAddRowsChanged(EventArgs.Empty);
                                        PrepareEditingRow (false, false);
+                                       Invalidate ();
                                }
                        }
                }
@@ -360,7 +361,10 @@ namespace System.Windows.Forms {
                                                }
                                        }
                                }
+                               
                                autoSizeColumnsMode = value;
+                               AutoResizeColumns (value);
+                               Invalidate ();
                        }
                }
 
@@ -376,7 +380,9 @@ namespace System.Windows.Forms {
                                                throw new InvalidOperationException("Cant set this property to AllHeaders or DisplayedHeaders in this DataGridView.");
                                        }
                                        autoSizeRowsMode = value;
+                                       AutoResizeRows (value);
                                        OnAutoSizeRowsModeChanged(new DataGridViewAutoSizeModeEventArgs(false));
+                                       Invalidate ();
                                        ////////////////////////////////////////////////////////////////
                                }
                        }
@@ -1013,9 +1019,9 @@ namespace System.Windows.Forms {
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                public DataGridViewRow RowTemplate {
                        get {
-                               if (rowTemplate == null) {
-                                       return new DataGridViewRow();
-                               }
+                               if (rowTemplate == null)
+                                       rowTemplate = new DataGridViewRow ();
+
                                return rowTemplate;
                        }
                        set {
@@ -2091,7 +2097,7 @@ namespace System.Windows.Forms {
                        DataGridViewRow row = GetRowInternal (rowIndex);
                        
                        if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader) {
-                               row.Height = row.HeaderCell.PreferredSize.Width;
+                               row.Height = row.HeaderCell.PreferredSize.Height;
                                return;
                        }
                        
@@ -2103,7 +2109,7 @@ namespace System.Windows.Forms {
                        if (autoSizeRowMode == DataGridViewAutoSizeRowMode.AllCellsExceptHeader)
                                row.Height = row_height;
                        else
-                               row.Height = Math.Max (row_height, row.HeaderCell.PreferredSize.Width);
+                               row.Height = Math.Max (row_height, row.HeaderCell.PreferredSize.Height);
                }
 
                public void AutoResizeRowHeadersWidth (DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
@@ -2329,6 +2335,9 @@ namespace System.Windows.Forms {
                        List<DataGridViewColumn> cols = columns.ColumnDisplayIndexSortedArrayList;
 
                        for (int i = first_col_index; i < cols.Count; i++) {
+                               if (!cols[i].Visible)
+                                       continue;
+                                       
                                if (cols[i].Index == columnIndex) {
                                        w = cols[i].Width;
                                        break;
@@ -2570,6 +2579,9 @@ namespace System.Windows.Forms {
                        List<DataGridViewColumn> cols = columns.ColumnDisplayIndexSortedArrayList;
 
                        for (int i = first_col_index; i < cols.Count; i++) {
+                               if (!cols[i].Visible)
+                                       continue;
+                                       
                                if (cols[i].Index == columnIndex) {
                                        w = cols[i].Width;
                                        break;
@@ -2651,6 +2663,9 @@ namespace System.Windows.Forms {
                        List<DataGridViewColumn> cols = columns.ColumnDisplayIndexSortedArrayList;
                        
                        for (int i = first_col_index; i < cols.Count; i++) {
+                               if (!cols[i].Visible)
+                                       continue;
+                                       
                                if (x > left && x <= (left + cols[i].Width)) {
                                        colindex = cols[i].Index;
                                        break;
@@ -2662,10 +2677,10 @@ namespace System.Windows.Forms {
                        if (colindex >= 0 && rowindex >= 0)
                                return new HitTestInfo (colindex, x, rowindex, y, DataGridViewHitTestType.Cell);
                        
-                       if (isInColHeader)
+                       if (isInColHeader && colindex > -1)
                                return new HitTestInfo (colindex, x, rowindex, y, DataGridViewHitTestType.ColumnHeader);
                        
-                       if (isInRowHeader)
+                       if (isInRowHeader && rowindex > -1)
                                return new HitTestInfo (colindex, x, rowindex, y, DataGridViewHitTestType.RowHeader);
                                
                        return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.None);
@@ -2812,21 +2827,43 @@ namespace System.Windows.Forms {
                
                public void UpdateCellErrorText (int columnIndex, int rowIndex)
                {
-                       throw new NotImplementedException();
+                       if (columnIndex < 0 || columnIndex > Columns.Count - 1)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+
+                       InvalidateCell (columnIndex, rowIndex);
                }
 
                public void UpdateCellValue (int columnIndex, int rowIndex)
                {
-                       throw new NotImplementedException();
+                       if (columnIndex < 0 || columnIndex > Columns.Count - 1)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       
+                       InvalidateCell (columnIndex, rowIndex);
                }
 
                public void UpdateRowErrorText (int rowIndex)
                {
-                       throw new NotImplementedException();
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+
+                       InvalidateRow (rowIndex);
                }
 
-               public void UpdateRowErrorText (int rowIndexStart, int rowIndexEnd) {
-                       throw new NotImplementedException();
+               public void UpdateRowErrorText (int rowIndexStart, int rowIndexEnd)
+               {
+                       if (rowIndexStart < 0 || rowIndexStart > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndexStart");
+                       if (rowIndexEnd < 0 || rowIndexEnd > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndexEnd");
+                       if (rowIndexEnd < rowIndexStart)
+                               throw new ArgumentOutOfRangeException ("rowIndexEnd", "rowIndexEnd must be greater than rowIndexStart");
+                               
+                       for (int i = rowIndexStart; i <= rowIndexEnd; i++)
+                               InvalidateRow (i);
                }
 
                public void UpdateRowHeightInfo (int rowIndex, bool updateToEnd) {
@@ -4162,6 +4199,9 @@ namespace System.Windows.Forms {
                                for (int index = first_col_index; index < sortedColumns.Count; index++) {
                                        DataGridViewColumn col = sortedColumns[index];
                                        
+                                       if (!col.Visible)
+                                               continue;
+                                       
                                        headerBounds.Width = col.Width;
                                        DataGridViewCell cell = col.HeaderCell;
 
@@ -4180,7 +4220,7 @@ namespace System.Windows.Forms {
                        gridHeight = 0;
                        
                        int rows_displayed = 0;
-                       int first_row_height = Rows.Count > 0 ? Rows[first_row_index].Height : 0;
+                       int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
                        int room_left = this.Height;
                        
                        // Reset all columns to !Displayed
@@ -4190,7 +4230,10 @@ namespace System.Windows.Forms {
                        // Set Displayed columns
                        for (int i = first_col_index; i < Columns.Count; i++) {
                                DataGridViewColumn col = Columns.ColumnDisplayIndexSortedArrayList[i];
-                               
+
+                               if (!col.Visible)
+                                       continue;
+                       
                                col.DisplayedInternal = true;
                                gridWidth += col.Width;
                                
@@ -4211,7 +4254,7 @@ namespace System.Windows.Forms {
                                bool is_first = row.Index == 0;
                                bool is_last = row.Index == rows.Count - 1;
 
-                               row.Paint (g, e.ClipRectangle, bounds, index, row.GetState (row.Index), is_first, is_last);
+                               row.Paint (g, e.ClipRectangle, bounds, row.Index, row.GetState (row.Index), is_first, is_last);
 
                                bounds.Y += bounds.Height;
                                bounds.X = BorderWidth;
@@ -4227,7 +4270,8 @@ namespace System.Windows.Forms {
                        gridWidth = 0;
                        
                        foreach (DataGridViewColumn col in sortedColumns)
-                               gridWidth += col.Width;
+                               if (col.Visible)
+                                       gridWidth += col.Width;
 
                        gridHeight = 0;
                        
@@ -4970,6 +5014,8 @@ namespace System.Windows.Forms {
 
                protected virtual void SetSelectedCellCore (int columnIndex, int rowIndex, bool selected) {
                        rows [rowIndex].Cells [columnIndex].Selected = selected;
+                       
+                       OnSelectionChanged (EventArgs.Empty);
                }
 
                internal void SetSelectedColumnCoreInternal (int columnIndex, bool selected) {
index 45abad5cb0162dcc5bada5b161dd1a5eadf2e95f..f4bd00750aeb8d2b4c46b9c971ee0ec917e8aa1f 100644 (file)
@@ -50,8 +50,8 @@ namespace System.Windows.Forms {
                private DataGridViewCellStyle style;
                private object tag;
                private string toolTipText;
-               private object valuex;
-               private Type valueType;
+               internal object valuex;
+               internal Type valueType;
 
                protected DataGridViewCell ()
                {
@@ -1009,9 +1009,10 @@ namespace System.Windows.Forms {
                                
                        DataGridViewCellFormattingEventArgs e = new DataGridViewCellFormattingEventArgs (ColumnIndex, rowIndex, value, FormattedValueType, cellStyle);
                        
-                       DataGridView.OnCellFormattingInternal (e);
+                       if (!(this is DataGridViewRowHeaderCell))
+                               DataGridView.OnCellFormattingInternal (e);
                        
-                       if (e.FormattingApplied) {
+                       if (e.FormattingApplied || e.Value != null) {
                                return e.Value;
                        }
                        
@@ -1239,10 +1240,10 @@ namespace System.Windows.Forms {
                                PaintPartBackground (graphics, cellBounds, cellStyle);
                        if ((paintParts & DataGridViewPaintParts.SelectionBackground) == DataGridViewPaintParts.SelectionBackground)
                                PaintPartSelectionBackground (graphics, cellBounds, cellState, cellStyle);
-                       if ((paintParts & DataGridViewPaintParts.Border) == DataGridViewPaintParts.Border)
-                               PaintPartBorder (graphics, cellBounds, rowIndex);
                        if ((paintParts & DataGridViewPaintParts.ContentForeground) == DataGridViewPaintParts.ContentForeground)
                                PaintPartContent (graphics, cellBounds, rowIndex, cellState, cellStyle, formattedValue);
+                       if ((paintParts & DataGridViewPaintParts.Border) == DataGridViewPaintParts.Border)
+                               PaintPartBorder (graphics, cellBounds, rowIndex);
                        if ((paintParts & DataGridViewPaintParts.Focus) == DataGridViewPaintParts.Focus)
                                PaintPartFocus (graphics, cellBounds);
                        if ((paintParts & DataGridViewPaintParts.ErrorIcon) == DataGridViewPaintParts.ErrorIcon)
@@ -1443,7 +1444,7 @@ namespace System.Windows.Forms {
                                formattedvalue = Value;
                        } else {
                                value = Value;
-                               formattedvalue = FormattedValue;
+                               formattedvalue = GetFormattedValue (Value, rowIndex, ref cellStyle, null, null, DataGridViewDataErrorContexts.Formatting);
                        }
 
                        DataGridViewCellPaintingEventArgs pea = new DataGridViewCellPaintingEventArgs (DataGridView, graphics, clipBounds, cellBounds, rowIndex, columnIndex, cellState, value, formattedvalue, ErrorText, cellStyle, advancedBorderStyle, paintParts);
index 7f7f7239101854503d50600ae6869705b7723fe8..4dc477c913a37e204774604b63935c360303b26a 100644 (file)
@@ -235,6 +235,8 @@ namespace System.Windows.Forms {
                                return false;
                        if (value == trueValue)
                                return true;
+                       if (value == DBNull.Value)
+                               return false;
                                
                        return Convert.ToBoolean (value);
                }
index 560261095d287470d0c9eac19ff783da29329648..d7ac279d672a8314dd1146a7399cad5c11f725ce 100644 (file)
@@ -137,8 +137,9 @@ namespace System.Windows.Forms {
                        }
                }
 
-               public override string ToString () {
-                       throw new NotImplementedException();
+               public override string ToString ()
+               {
+                       return string.Format ("DataGridViewCheckBoxColumn {{ Name={0}, Index={1} }}", Name, Index);
                }
 
        }
index ea936ca403d192b6843cb05e0c363fa9b7190353..d3c010f3e5289cfb48000eff9ce84cb4cf7d83bc 100644 (file)
@@ -61,7 +61,7 @@ namespace System.Windows.Forms {
                }
 
                public override int GetHashCode () {
-                       throw new NotImplementedException();
+                       return base.GetHashCode ();
                }
 
                public override bool IsDefaultAttribute () {
index ded0b150210bdfe722d16693278f0a8edc4d08c7..2ec152451f61ec238141ddf977b302a73b7fc78a 100644 (file)
@@ -219,6 +219,10 @@ namespace System.Windows.Forms {
 
                        // Postpaint
                        DataGridViewPaintParts post = DataGridViewPaintParts.Border;
+                       
+                       if (this is DataGridViewTopLeftHeaderCell)
+                               post |= DataGridViewPaintParts.ErrorIcon;
+                               
                        post = post & paintParts;
 
                        base.Paint (graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, post);
index f9019c490bcb1f342ea7d7e369c1d95e0357cfcc..5079ce39f07bc4502740172a4c42bf2bfdec6ca6 100644 (file)
@@ -52,8 +52,8 @@ namespace System.Windows.Forms {
                        get { return state; }
                }
 
-               protected virtual void OnDataGridViewChanged () {
-                       throw new NotImplementedException();
+               protected virtual void OnDataGridViewChanged ()
+               {
                }
 
                protected void RaiseCellClick (DataGridViewCellEventArgs e) {
index 2d10dc80b1b92cc99ce23088443efe240c5abab2..43844c0f7efe03e1960057c5dc681e8398a479f3 100644 (file)
@@ -163,7 +163,9 @@ namespace System.Windows.Forms
                                if (headerCell != value) {
                                        headerCell = value;
                                        headerCell.SetOwningRow (this);
+                                       
                                        if (DataGridView != null) {
+                                               headerCell.SetDataGridView (DataGridView);
                                                DataGridView.OnRowHeaderCellChanged(new DataGridViewRowEventArgs(this));
                                        }
                                }
@@ -331,12 +333,18 @@ namespace System.Windows.Forms
 
                public override object Clone ()
                {
-                       DataGridViewRow row = (DataGridViewRow) MemberwiseClone();
-                       row.HeaderCell.SetOwningRow (row);
-                       row.cells = new DataGridViewCellCollection(row);
-                       foreach (DataGridViewCell cell in cells) {
-                               row.cells.Add(cell.Clone() as DataGridViewCell);
-                       }
+                       DataGridViewRow row = (DataGridViewRow)MemberwiseClone ();
+
+                       row.HeaderCell = (DataGridViewRowHeaderCell)HeaderCell.Clone ();
+                       row.SetIndex (-1);
+                       
+                       row.cells = new DataGridViewCellCollection (row);
+                       
+                       foreach (DataGridViewCell cell in cells)
+                               row.cells.Add (cell.Clone () as DataGridViewCell);
+
+                       row.SetDataGridView (null);
+
                        return row;
                }
 
@@ -518,6 +526,9 @@ namespace System.Windows.Forms
                        for (int i = DataGridView.first_col_index; i < sortedColumns.Count; i++) {
                                DataGridViewColumn col = sortedColumns[i];
                                
+                               if (!col.Visible)
+                                       continue;
+                                       
                                if (!col.Displayed)
                                        break;
                                        
index 1f446d8cfd5f65c71cbc616e5efc173f56c8b440..f98f92f6260971bd269299e713ab5186307be6d3 100644 (file)
@@ -156,16 +156,19 @@ namespace System.Windows.Forms
                
                private bool CanBeShared (DataGridViewRow row)
                {
-                       foreach (DataGridViewCell cell in row.Cells) {
-                               if (cell.Value != null)
-                                       return false;
-                               if (cell.ToolTipText != string.Empty)
-                                       return false;
-                               if (cell.ContextMenuStrip != null)
-                                       return false;
-                       }
-
-                       return true;
+                       // We don't currently support shared rows
+                       return false;
+                       
+                       //foreach (DataGridViewCell cell in row.Cells) {
+                       //        if (cell.Value != null)
+                       //                return false;
+                       //        if (cell.ToolTipText != string.Empty)
+                       //                return false;
+                       //        if (cell.ContextMenuStrip != null)
+                       //                return false;
+                       //}
+
+                       //return true;
                }
                
 
index bafe748f3b9ac9194677eaddda9ac1b99ca70b3b..6e78576891fddec75ff682857f583a7e4a479ad6 100644 (file)
@@ -95,12 +95,12 @@ namespace System.Windows.Forms {
                        
                        editingControl.EditingControlDataGridView = DataGridView;
                        editingControl.MaxLength = maxInputLength;
-                       if (initialFormattedValue == null || (string) initialFormattedValue == "") {
-                               editingControl.Text = "";
-                       }
-                       else {
-                               editingControl.Text = (string) initialFormattedValue;
-                       }
+                       
+                       if (initialFormattedValue == null || initialFormattedValue.ToString () == string.Empty)
+                               editingControl.Text = string.Empty;
+                       else
+                               editingControl.Text = initialFormattedValue.ToString ();
+
                        editingControl.ApplyCellStyleToEditingControl(dataGridViewCellStyle);
                        editingControl.PrepareEditingControlForEdit(true);
                }
index b9fc7ddbde6fbd8ffe1286a455485b52166c63dd..09e3843ba889db9ec303fec64bf6bfa6a807bc1c 100644 (file)
@@ -31,30 +31,26 @@ using System.Globalization;
 
 namespace System.Windows.Forms {
        public class InputLanguageCollection : ReadOnlyCollectionBase {
-               #region Local Variables
-               internal InputLanguage[]        list;
-               #endregion      // Local Variables
-
                #region Private Constructor
                internal InputLanguageCollection (InputLanguage[] data)
                {
-                       list = data;
+                       base.InnerList.AddRange (data);
                }
                #endregion      // Private Constructor
 
                #region Public Instance Methods
                public InputLanguage this [int index] {
                        get {
-                               if (index>=list.Length) {
+                               if (index >= base.InnerList.Count) {
                                        throw new ArgumentOutOfRangeException("index");
                                }
-                               return list[index];
+                               return base.InnerList[index] as InputLanguage;
                        }
                }
 
                public bool Contains(InputLanguage value) {
-                       for (int i=0; i<list.Length; i++) {
-                               if ((list[i].Culture==value.Culture) && (list[i].LayoutName==value.LayoutName)) {
+                       for (int i = 0; i < base.InnerList.Count; i++) {
+                               if ((this[i].Culture == value.Culture) && (this[i].LayoutName == value.LayoutName)) {
                                        return true;
                                }
                        }
@@ -62,14 +58,14 @@ namespace System.Windows.Forms {
                }
 
                public void CopyTo(InputLanguage[] array, int index) {
-                       if (list.Length>0) {
-                               Array.Copy(list, 0, array, index, list.Length);
+                       if (base.InnerList.Count > 0) {
+                               base.InnerList.CopyTo (array, index);
                        }
                }
 
                public int IndexOf(InputLanguage value) {
-                       for (int i=0; i<list.Length; i++) {
-                               if ((list[i].Culture==value.Culture) && (list[i].LayoutName==value.LayoutName)) {
+                       for (int i = 0; i < base.InnerList.Count; i++) {
+                               if ((this[i].Culture == value.Culture) && (this[i].LayoutName == value.LayoutName)) {
                                        return i;
                                }
                        }
index e5c435910aca66dbf8141146781280f1ba9fcf75..d9127fe4e304b19744ac77068cd1fec91e3f9e63 100644 (file)
@@ -192,7 +192,7 @@ namespace System.Windows.Forms
 
                protected internal virtual void OnDropDownItemClicked (ToolStripItemClickedEventArgs e)
                {
-                       ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [DropDownClosedEvent]);
+                       ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [DropDownItemClickedEvent]);
                        if (eh != null)
                                eh (this, e);
                }
index d452a9d2e9985308a233a5d092c459434baa1576..53ed64983bda7875f19bdac7a30533386792a1f0 100644 (file)
@@ -241,6 +241,9 @@ namespace System.Windows.Forms
                                return;
                        }
                                
+                       if (this.OwnerItem is ToolStripDropDownItem)
+                               (this.OwnerItem as ToolStripDropDownItem).OnDropDownItemClicked (new ToolStripItemClickedEventArgs (this));
+
                        if (this.IsOnDropDown)
                                this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
 
index f1475569305225206698fad933c35dc045a907ce..0c0b5e54c61cead30db42ccd8c6fc41455ad5c89 100644 (file)
@@ -1,3 +1,13 @@
+2008-05-01  Jonathan Pobst  <monkey@jpobst.com>
+
+       * DataGridViewRowCollectionTest.cs: Disable test requiring shared rows.
+       * DataGridViewRowTest.cs, DataGridViewCellTest.cs: Disable
+       tests requiring DGVComboBox.
+
+2008-05-01  Jonathan Pobst  <monkey@jpobst.com>
+
+       * InputLanguageTest.cs: Add test for bug #385506.
+
 2008-04-29  Carlos Alberto Cortez <calberto.cortez@gmail.com>
 
        * BindingSourceTest.cs: New Filter/RemoveFilter tests.
index 1c1785250961b050787d2a80f57300cd87a383f5..ca5b373faf87dbe51d6b018d52b02fe33bf1583c 100644 (file)
@@ -322,6 +322,7 @@ namespace MonoTests.System.Windows.Forms
                }
 
                [Test]
+               [NUnit.Framework.Category ("NotWorking")]       // DGVComboBox not implemented
                public void AddRow_Changes ()
                {
                        using (DataGridView dgv = new DataGridView ()) {
index 743de5382a88a17ed0854ceb1fcd5aecba6aedfa..c7ac540553ec3fa4d6b65003ae7dd8d85371e1f2 100644 (file)
@@ -76,6 +76,7 @@ namespace MonoTests.System.Windows.Forms
                }
                
                [Test]
+               [NUnit.Framework.Category ("NotWorking")]       // Don't currently support shared rows
                public void AddTest ()
                {
                        DataGridViewRow row;
index 2ef43c7fc15792a12c76d970749b44554f69b34e..f99ab1fb8597768aa7757ded17447e09be91d81b 100644 (file)
@@ -90,6 +90,7 @@ namespace MonoTests.System.Windows.Forms {
                
 
                [Test]
+               [NUnit.Framework.Category ("NotWorking")]       // DGVComboBox not implemented
                public void AddRow_Changes ()
                {
 
@@ -348,6 +349,35 @@ namespace MonoTests.System.Windows.Forms {
                        Assert.IsNull (row.Tag, "#A row.Tag");
                        Assert.AreEqual (true, row.Visible, "#A row.Visible");
                }
+               
+               [Test]
+               public void Clone ()
+               {
+                       DataGridView dgv = new DataGridView ();
+
+                       dgv.Columns.Add ("Column 1", "Column 1");
+                       dgv.Columns.Add ("Column 2", "Column 2");
+                       
+                       dgv.Rows.Add ("Cell 1", "Cell 2");
+                       
+                       DataGridViewRow row1 = dgv.Rows[0];
+                       
+                       row1.ErrorText = "Yikes!";
+                       row1.Tag = "Helo";
+                       row1.ReadOnly = true;
+                       row1.Visible = false;
+                       
+                       DataGridViewRow row2 = (DataGridViewRow)row1.Clone ();
+
+                       Assert.AreEqual (2, row2.Cells.Count, "A1");
+                       Assert.AreEqual (null, row2.DataGridView, "A3");
+                       Assert.AreEqual ("Yikes!", row2.ErrorText, "A4");
+                       Assert.AreEqual (-1, row2.HeaderCell.RowIndex, "A5");
+                       Assert.AreEqual (-1, row2.Index, "A6");
+                       Assert.AreEqual (true, row2.ReadOnly, "A7");
+                       Assert.AreEqual ("Helo", row2.Tag, "A8");
+                       Assert.AreEqual (false, row2.Visible, "A9");
+               }
        }
 }
 #endif
index ccbf04244595b6b71b6258931a965dd762b88778..66fd0246c11b2e0df03dc9605ce18cd85cb682ec 100644 (file)
@@ -43,6 +43,12 @@ namespace MonoTests.System.Windows.Forms
                {
                        InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;
                }
+
+               [Test]
+               public void InstalledInputLanguages_HasAtLeastOneLanguage ()
+               {
+                       Assert.IsTrue (InputLanguage.InstalledInputLanguages.Count > 0);
+               }
        }
 }
 #endif
\ No newline at end of file
index eb78d6d8629ff15c26328fdadb16fa12b8f29725..5fde911341f18f6a1444105ebb671b3e714f27a5 100644 (file)
@@ -1,3 +1,7 @@
+2008-05-01  Jb Evain  <jbevain@novell.com>
+
+       * System.Core-2008.csproj, System.Core.dll.sources: add new files.
+
 2008-03-27  Leonid Freydovich  <leonidf@mainsoft.com>
 
        * Add some TARGET_JVM specific code
@@ -10,7 +14,7 @@
 2007-12-04  Marek Safar  <marek.safar@gmail.com>
 
        * System.Core.dll.sources: System.Linq.Expression refresh.
-       
+
 2007-08-20  Marek Safar  <marek.safar@gmail.com>
 
        * Makefile: Hardcoded 3.5 define for now.
@@ -27,7 +31,7 @@
        * Implemented somme missing stuff in BinaryExpression.
 
        * The stuff in ExpressionUtils is very generic and does quite some
-       redundant checks: I started splitting the stuff there into more   
+       redundant checks: I started splitting the stuff there into more
        "specific" methods that should be both understandable and fast.
 
        * Fixed the StringBuilder problem, added unique IDs to all tests,
@@ -59,7 +63,7 @@
 2007-03-29  Miguel de Icaza  <miguel@novell.com>
 
        * Reapply the patch from Antonello, and rework the code to not use
-       extension methods on Enumerable. 
+       extension methods on Enumerable.
 
 2007-02-04  Marek Safar  <marek.safar@gmail.com>
 
index a2354c6decfc151eb0110d8d3f90d9274ac3bdf9..4f1cf58f6537102aa7a8675fbe1c3ab386df1c44 100755 (executable)
     <Compile Include="System.Linq.Expressions\ParameterExpression.cs" />\r
     <Compile Include="System.Linq.Expressions\TypeBinaryExpression.cs" />\r
     <Compile Include="System.Linq.Expressions\UnaryExpression.cs" />\r
-    <Compile Include="System.Linq\AOrderedEnumerable.cs" />\r
     <Compile Include="System.Linq\Check.cs" />\r
+    <Compile Include="System.Linq\QuickSort.cs" />\r
+    <Compile Include="System.Linq\SortSequenceContext.cs" />\r
+    <Compile Include="System.Linq\SortContext.cs" />\r
     <Compile Include="System.Linq\Enumerable.cs" />\r
+    <Compile Include="System.Linq\SortDirection.cs" />\r
     <Compile Include="System.Linq\Grouping.cs" />\r
     <Compile Include="System.Linq\IGrouping.cs" />\r
     <Compile Include="System.Linq\ILookup_T.cs" />\r
-    <Compile Include="System.Linq\InternalOrderedSequence.cs" />\r
     <Compile Include="System.Linq\IOrderedEnumerable_T.cs" />\r
     <Compile Include="System.Linq\IOrderedQueryable.cs" />\r
     <Compile Include="System.Linq\IOrderedQueryable_T.cs" />\r
@@ -87,6 +89,8 @@
     <Compile Include="System.Linq\IQueryable_T.cs" />\r
     <Compile Include="System.Linq\IQueryProvider.cs" />\r
     <Compile Include="System.Linq\Lookup.cs" />\r
+    <Compile Include="System.Linq\OrderedEnumerable.cs" />\r
+    <Compile Include="System.Linq\OrderedSequence.cs" />\r
     <Compile Include="System.Linq\Queryable.cs" />\r
     <Compile Include="System.Runtime.CompilerServices\ExecutionScope.cs" />\r
     <Compile Include="System.Runtime.CompilerServices\ExtensionAttribute.cs" />\r
index dbe3fdf1811c13d4b12323335776a2b767650536..fbd78daa6ba058cad4139e2b562fe5571ccc5842 100644 (file)
@@ -17,7 +17,6 @@ System.Linq/Check.cs
 System.Linq/Enumerable.cs
 System.Linq/Grouping.cs
 System.Linq/IGrouping.cs
-System.Linq/InternalOrderedSequence.cs
 System.Linq/IOrderedQueryable.cs
 System.Linq/IOrderedQueryable_T.cs
 System.Linq/IOrderedEnumerable_T.cs
@@ -25,8 +24,13 @@ System.Linq/IQueryable.cs
 System.Linq/IQueryable_T.cs
 System.Linq/Lookup.cs
 System.Linq/ILookup_T.cs
-System.Linq/AOrderedEnumerable.cs
+System.Linq/OrderedEnumerable.cs
+System.Linq/OrderedSequence.cs
 System.Linq/Queryable.cs
+System.Linq/QuickSort.cs
+System.Linq/SortContext.cs
+System.Linq/SortDirection.cs
+System.Linq/SortSequenceContext.cs
 System.Linq/IQueryProvider.cs
 System.Linq.Expressions/BinaryExpression.cs
 System.Linq.Expressions/ConditionalExpression.cs
diff --git a/mcs/class/System.Core/System.Linq/AOrderedEnumerable.cs b/mcs/class/System.Core/System.Linq/AOrderedEnumerable.cs
deleted file mode 100644 (file)
index a6131b2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// AOrderedEnumerable.cs
-//
-// Authors:
-//     Marek Safar  <marek.safar@gmail.com>
-//
-// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Linq
-{
-        abstract class AOrderedEnumerable<TElement> : IOrderedEnumerable<TElement>
-        {
-               protected AOrderedEnumerable<TElement> parent;
-                       
-               public abstract IEnumerator<TElement> GetEnumerator ();
-                public abstract IEnumerable<TElement> Sort (IEnumerable<TElement> parentSource);
-                
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       return GetEnumerator ();
-               }
-                        
-               public IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey> (
-                       Func<TElement, TKey> selector, IComparer<TKey> comparer, bool descending)
-               {
-                       parent = new InternalOrderedSequence<TElement, TKey> (this, selector, comparer, descending);
-                       return parent;
-               }
-        }
-}
-
index 2b49cc0b7623c8f5a863e11d3c0b66b16eff1f3a..907ca5f2c9c9ab2331114764cf31602e2f45586f 100644 (file)
@@ -1,3 +1,16 @@
+2008-05-01  Jb Evain  <jbevain@novell.com>
+
+       * SortDirection.cs, SortContext.cs, SortSequenceContext.cs:
+       new infrastructure files for nested orderby/thenby calls.
+       * QuickSort.cs: refactored out of OrderedSequence.cs
+       * OrderedEnumerable.cs, OrderedSequence.cs: refactoring
+       to use the new SortContext infrastructure.
+
+2008-04-30  Jb Evain  <jbevain@novell.com>
+
+       * Enumerable.cs: Average (int|long): properly compute
+       average.
+
 2008-04-22  Jb Evain  <jbevain@novell.com>
 
        * Enumerable.cs (ToReadOnlyCollection): optimization, use
index 9d55a55ff3d24181051de4e713728c4e6e182ee9..3cad6b08da7707553e4fc8e4dcfd0993157b6580 100644 (file)
@@ -137,12 +137,12 @@ namespace System.Linq
 
                public static double Average (this IEnumerable<int> source)
                {
-                       return Average (source, (a, b) => a + b, (a, b) => a / b);
+                       return Average (source, (a, b) => a + b, (a, b) => (double) a / (double) b);
                }
 
                public static double Average (this IEnumerable<long> source)
                {
-                       return Average (source, (a, b) => a + b, (a, b) => a / b);
+                       return Average (source, (a, b) => a + b, (a, b) => (double) a / (double) b);
                }
 
                public static double Average (this IEnumerable<double> source)
@@ -1603,15 +1603,14 @@ namespace System.Linq
                        return OrderBy<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
                                Func<TSource, TKey> keySelector,
                                IComparer<TKey> comparer)
                {
                        Check.SourceAndKeySelector (source, keySelector);
 
-                       return new InternalOrderedSequence<TSource, TKey> (
-                                       source, keySelector, comparer, false);
+                       return new OrderedSequence<TSource, TKey> (
+                                       source, keySelector, comparer, SortDirection.Ascending);
                }
 
                #endregion
@@ -1624,14 +1623,13 @@ namespace System.Linq
                        return OrderByDescending<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
                                Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
                {
                        Check.SourceAndKeySelector (source, keySelector);
 
-                       return new InternalOrderedSequence<TSource, TKey> (
-                                       source, keySelector, comparer, true);
+                       return new OrderedSequence<TSource, TKey> (
+                                       source, keySelector, comparer, SortDirection.Descending);
                }
 
                #endregion
@@ -2207,7 +2205,6 @@ namespace System.Linq
                        return ThenBy<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
                        Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
                {
@@ -2226,7 +2223,6 @@ namespace System.Linq
                        return ThenByDescending<TSource, TKey> (source, keySelector, null);
                }
 
-
                public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
                        Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
                {
diff --git a/mcs/class/System.Core/System.Linq/InternalOrderedSequence.cs b/mcs/class/System.Core/System.Linq/InternalOrderedSequence.cs
deleted file mode 100644 (file)
index e8e72c9..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// InternalOrderedSequence.cs
-//
-// Authors:
-//     Alejandro Serrano "Serras" (trupill@yahoo.es)
-//     Marek Safar  <marek.safar@gmail.com>
-//
-// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace System.Linq
-{
-       sealed class InternalOrderedSequence<TElement, TKey> : AOrderedEnumerable<TElement>
-        {
-               readonly IEnumerable<TElement> source;
-               readonly Func<TElement, TKey> key_selector;
-               readonly IComparer<TKey> comparer;
-               readonly bool descending;
-                
-                internal InternalOrderedSequence (IEnumerable<TElement> source, Func<TElement, TKey> keySelector,
-                                                  IComparer<TKey> comparer, bool descending)
-                {
-                        this.source = source;
-                        this.key_selector = keySelector;
-                        this.comparer = comparer ?? Comparer<TKey>.Default;
-                        this.descending = descending;
-                }
-                
-                public override IEnumerable<TElement> Sort (IEnumerable<TElement> parentSource)
-                {
-                        if (parent != null)
-                                return parent.Sort (source);
-                        return PerformSort (parentSource);
-                }
-                
-                public override IEnumerator<TElement> GetEnumerator ()
-                {
-                        return PerformSort (source).GetEnumerator ();
-                }
-                
-                List<TElement> source_list;
-                TKey[] keys;
-                int[] indexes;
-                
-                IEnumerable<TElement> PerformSort (IEnumerable<TElement> items)
-                {
-                        // It first enumerates source, collecting all elements
-                        source_list = new List<TElement> (items);
-                        
-                        // If the source contains just zero or one element, there's no need to sort
-                        if (source_list.Count <= 1)
-                                return source_list;
-                        
-                        // Then evaluate the keySelector function for each element,
-                        // collecting the key values
-                        keys = new TKey [source_list.Count];
-                        indexes = new int [source_list.Count];
-                        for (int i = 0; i < source_list.Count; i++) {
-                                keys [i] = key_selector (source_list [i]);
-                                indexes [i] = i;
-                        }
-                        
-                        // Then sorts the elements according to the collected
-                        // key values and the selected ordering
-                        QuickSort(0, indexes.Length - 1);
-                        
-                        // Return the values as IEnumerable<TElement>
-                        TElement[] orderedList = new TElement [indexes.Length];
-                        for (int i = 0; i < indexes.Length; i++)
-                                orderedList [i] = source_list [indexes [i]];
-                        return orderedList;
-                }
-                
-                int CompareItems (int firstIndex, int secondIndex)
-                {
-                        int comparison = comparer.Compare (keys [firstIndex], keys [secondIndex]);
-                       
-                        // If descending, return the opposite comparison
-                        return (descending ? -comparison : comparison);
-                }
-                
-                // We look at the first, middle, and last items in the subarray.
-                // Then we put the largest on the right side, the smallest on
-                // the left side, and the median becomes our pivot.
-                int MedianOfThree (int left, int right)
-                {
-                        int center = (left + right) / 2;
-                        if (CompareItems (indexes [center], indexes [left]) < 0)
-                                Swap (left, center);
-                        if (CompareItems (indexes [right], indexes [left]) < 0)
-                                Swap (left, right);
-                        if (CompareItems (indexes [right], indexes [center]) < 0)
-                                Swap (center, right);
-                        Swap (center, right - 1);
-                        return indexes [right - 1];
-                }
-                
-                void QuickSort (int left, int right)
-                {
-                        if (left + 3 <= right) {
-                                int l = left, r = right - 1, pivot = MedianOfThree (left, right);
-                                while (true) {
-                                        while (CompareItems (indexes [++l], pivot) < 0) {}
-                                        while (CompareItems (indexes [--r], pivot) > 0) {}
-                                        if (l < r)
-                                                Swap (l, r);
-                                        else
-                                                break;
-                                }
-                                // Restore pivot
-                                Swap (l, right - 1);
-                                // Partition and sort
-                                QuickSort (left, l - 1);
-                                QuickSort (l + 1, right);
-                        } else
-                                // If there are three items in the subarray, insertion sort is better
-                                InsertionSort (left, right);
-                }
-                
-                void InsertionSort (int left, int right)
-                {
-                        for (int i = left + 1; i <= right; i++) {
-                                int j, tmp = indexes [i];
-                                for (j = i; j > left && CompareItems (tmp, indexes [j - 1]) < 0; j--)
-                                     indexes [j] = indexes [j - 1];
-                                indexes [j] = tmp;
-                        }
-                }
-                
-                void Swap (int left, int right)
-                {
-                        int temp = indexes [right];
-                        indexes [right] = indexes [left];
-                        indexes [left] = temp;
-                }
-                
-        }
-}
diff --git a/mcs/class/System.Core/System.Linq/OrderedEnumerable.cs b/mcs/class/System.Core/System.Linq/OrderedEnumerable.cs
new file mode 100644 (file)
index 0000000..b7e90f2
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// OrderedEnumerable.cs
+//
+// Authors:
+//     Marek Safar  <marek.safar@gmail.com>
+//     Jb Evain  <jbevain@novell.com>
+//
+// Copyright (C) 2007 - 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq {
+
+       abstract class OrderedEnumerable<TElement> : IOrderedEnumerable<TElement> {
+
+               IEnumerable<TElement> source;
+
+               protected OrderedEnumerable (IEnumerable<TElement> source)
+               {
+                       this.source = source;
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
+
+               public IEnumerator<TElement> GetEnumerator ()
+               {
+                       return Sort (source).GetEnumerator ();
+               }
+
+               public abstract SortContext<TElement> CreateContext (SortContext<TElement> current);
+
+               protected abstract IEnumerable<TElement> Sort (IEnumerable<TElement> source);
+
+               public IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey> (
+                       Func<TElement, TKey> selector, IComparer<TKey> comparer, bool descending)
+               {
+                       return new OrderedSequence<TElement, TKey> (this, source, selector, comparer,
+                               descending ? SortDirection.Descending : SortDirection.Ascending);
+               }
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/OrderedSequence.cs b/mcs/class/System.Core/System.Linq/OrderedSequence.cs
new file mode 100644 (file)
index 0000000..62bd024
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// OrderedSequence.cs
+//
+// Authors:
+//     Alejandro Serrano "Serras" (trupill@yahoo.es)
+//     Marek Safar  <marek.safar@gmail.com>
+//     Jb Evain  <jbevain@novell.com>
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq {
+
+       class OrderedSequence<TElement, TKey> : OrderedEnumerable<TElement> {
+
+               OrderedEnumerable<TElement> parent;
+
+               Func<TElement, TKey> selector;
+               IComparer<TKey> comparer;
+               SortDirection direction;
+
+               internal OrderedSequence (IEnumerable<TElement> source, Func<TElement, TKey> key_selector, IComparer<TKey> comparer, SortDirection direction)
+                       : base (source)
+               {
+                       this.selector = key_selector;
+                       this.comparer = comparer ?? Comparer<TKey>.Default;
+                       this.direction = direction;
+               }
+
+               internal OrderedSequence (OrderedEnumerable<TElement> parent, IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, SortDirection direction)
+                       : this (source, keySelector, comparer, direction)
+               {
+                       this.parent = parent;
+               }
+
+               public override SortContext<TElement> CreateContext (SortContext<TElement> current)
+               {
+                       SortContext<TElement> context = new SortSequenceContext<TElement, TKey> (selector, comparer, direction, current);
+
+                       if (parent != null)
+                               return parent.CreateContext (context);
+
+                       return context;
+               }
+
+               protected override IEnumerable<TElement> Sort (IEnumerable<TElement> source)
+               {
+                       return QuickSort<TElement>.Sort (source, CreateContext (null));
+               }
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/QuickSort.cs b/mcs/class/System.Core/System.Linq/QuickSort.cs
new file mode 100644 (file)
index 0000000..f64df40
--- /dev/null
@@ -0,0 +1,144 @@
+//
+// QuickSort.cs
+//
+// Authors:
+//   Alejandro Serrano "Serras" (trupill@yahoo.es)
+//   Marek Safar  <marek.safar@gmail.com>
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2007 - 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Linq {
+
+       class QuickSort<TElement> {
+
+               TElement [] elements;
+               int [] indexes;
+               SortContext<TElement> context;
+
+               QuickSort (IEnumerable<TElement> source, SortContext<TElement> context)
+               {
+                       this.elements = source.ToArray ();
+                       this.indexes = CreateIndexes (elements.Length);
+                       this.context = context;
+               }
+
+               static int [] CreateIndexes (int length)
+               {
+                       var indexes = new int [length];
+                       for (int i = 0; i < length; i++)
+                               indexes [i] = i;
+
+                       return indexes;
+               }
+
+               void PerformSort ()
+               {
+                       // If the source contains just zero or one element, there's no need to sort
+                       if (elements.Length <= 1)
+                               return;
+
+                       context.Initialize (elements);
+
+                       // Then sorts the elements according to the collected
+                       // key values and the selected ordering
+                       Sort (0, indexes.Length - 1);
+               }
+
+               int CompareItems (int first_index, int second_index)
+               {
+                       return context.Compare (first_index, second_index);
+               }
+
+               // We look at the first, middle, and last items in the subarray.
+               // Then we put the largest on the right side, the smallest on
+               // the left side, and the median becomes our pivot.
+               int MedianOfThree (int left, int right)
+               {
+                       int center = (left + right) / 2;
+                       if (CompareItems (indexes [center], indexes [left]) < 0)
+                               Swap (left, center);
+                       if (CompareItems (indexes [right], indexes [left]) < 0)
+                               Swap (left, right);
+                       if (CompareItems (indexes [right], indexes [center]) < 0)
+                               Swap (center, right);
+                       Swap (center, right - 1);
+                       return indexes [right - 1];
+               }
+
+               void Sort (int left, int right)
+               {
+                       if (left + 3 <= right) {
+                               int l = left, r = right - 1, pivot = MedianOfThree (left, right);
+                               while (true) {
+                                       while (CompareItems (indexes [++l], pivot) < 0) { }
+                                       while (CompareItems (indexes [--r], pivot) > 0) { }
+                                       if (l < r)
+                                               Swap (l, r);
+                                       else
+                                               break;
+                               }
+
+                               // Restore pivot
+                               Swap (l, right - 1);
+                               // Partition and sort
+                               Sort (left, l - 1);
+                               Sort (l + 1, right);
+                       } else
+                               // If there are three items in the subarray, insertion sort is better
+                               InsertionSort (left, right);
+               }
+
+               void InsertionSort (int left, int right)
+               {
+                       for (int i = left + 1; i <= right; i++) {
+                               int j, tmp = indexes [i];
+
+                               for (j = i; j > left && CompareItems (tmp, indexes [j - 1]) < 0; j--)
+                                       indexes [j] = indexes [j - 1];
+
+                               indexes [j] = tmp;
+                       }
+               }
+
+               void Swap (int left, int right)
+               {
+                       int temp = indexes [right];
+                       indexes [right] = indexes [left];
+                       indexes [left] = temp;
+               }
+
+               public static IEnumerable<TElement> Sort (IEnumerable<TElement> source, SortContext<TElement> context)
+               {
+                       var sorter = new QuickSort<TElement> (source, context);
+
+                       sorter.PerformSort ();
+
+                       for (int i = 0; i < sorter.indexes.Length; i++)
+                               yield return sorter.elements [sorter.indexes [i]];
+               }
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/SortContext.cs b/mcs/class/System.Core/System.Linq/SortContext.cs
new file mode 100644 (file)
index 0000000..1485117
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// SortContext.cs
+//
+// Author:
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Linq {
+
+       abstract class SortContext<TElement> {
+
+               protected SortDirection direction;
+               protected SortContext<TElement> child_context;
+
+               protected SortContext (SortDirection direction, SortContext<TElement> child_context)
+               {
+                       this.direction = direction;
+                       this.child_context = child_context;
+               }
+
+               public abstract void Initialize (TElement [] elements);
+
+               public abstract int Compare (int first_index, int second_index);
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/SortDirection.cs b/mcs/class/System.Core/System.Linq/SortDirection.cs
new file mode 100644 (file)
index 0000000..231aa8e
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// SortDirection.cs
+//
+// Author:
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Linq {
+
+       enum SortDirection {
+               Ascending,
+               Descending
+       }
+}
diff --git a/mcs/class/System.Core/System.Linq/SortSequenceContext.cs b/mcs/class/System.Core/System.Linq/SortSequenceContext.cs
new file mode 100644 (file)
index 0000000..67fd2b3
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// SortSequenceContext.cs
+//
+// Author:
+//   Jb Evain (jbevain@novell.com)
+//
+// (C) 2008 Novell, Inc. (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Linq {
+
+       class SortSequenceContext<TElement, TKey> : SortContext<TElement> {
+
+               Func<TElement, TKey> selector;
+               IComparer<TKey> comparer;
+
+               TKey [] keys;
+
+               public SortSequenceContext (Func<TElement, TKey> selector, IComparer<TKey> comparer, SortDirection direction, SortContext<TElement> child_context)
+                       : base (direction, child_context)
+               {
+                       this.selector = selector;
+                       this.comparer = comparer;
+               }
+
+               public override void Initialize (TElement [] elements)
+               {
+                       if (child_context != null)
+                               child_context.Initialize (elements);
+
+                       keys = new TKey [elements.Length];
+                       for (int i = 0; i < keys.Length; i++)
+                               keys [i] = selector (elements [i]);
+               }
+
+               public override int Compare (int first_index, int second_index)
+               {
+                       int comparison = comparer.Compare (keys [first_index], keys [second_index]);
+
+                       if (comparison == 0 && child_context != null)
+                               comparison = child_context.Compare (first_index, second_index);
+
+                       return direction == SortDirection.Descending ? -comparison : comparison;
+               }
+       }
+}
index dcdfa2d370837540a3adc933a7d3a4c12433ffe3..8339163790b78bb9430c360ce04974e6fb1679a3 100644 (file)
@@ -239,6 +239,17 @@ namespace MonoTests.System.Linq.Expressions {
                        Assert.IsNotNull (c.Method);
                }
 
+               [Test]
+               [Category ("NotWorking")]
+               public void CompileConvertClassWithExplicitOp ()
+               {
+                       var p = Expression.Parameter (typeof (Klang), "klang");
+                       var c = Expression.Lambda<Func<Klang, int>> (
+                               Expression.Convert (p, typeof (int)), p).Compile ();
+
+                       Assert.AreEqual (42, c (new Klang (42)));
+               }
+
                [Test]
                public void ConvertClassWithExplicitOpToNullableInt ()
                {
@@ -249,7 +260,7 @@ namespace MonoTests.System.Linq.Expressions {
                        Assert.IsNotNull (c.Method);
                }
 
-               class Kling {
+               struct Kling {
                        int i;
 
                        public Kling (int i)
@@ -264,7 +275,7 @@ namespace MonoTests.System.Linq.Expressions {
                }
 
                [Test]
-               public void ConvertClassWithImplicitOp ()
+               public void ConvertStructWithImplicitOp ()
                {
                        var c = Expression.Convert (Expression.Parameter (typeof (Kling), ""), typeof (int));
                        Assert.AreEqual (typeof (int), c.Type);
@@ -274,7 +285,18 @@ namespace MonoTests.System.Linq.Expressions {
                }
 
                [Test]
-               public void ConvertClassWithImplicitOpToNullableInt ()
+               [Category ("NotWorking")]
+               public void CompileConvertStructWithImplicitOp ()
+               {
+                       var p = Expression.Parameter (typeof (Kling), "kling");
+                       var c = Expression.Lambda<Func<Kling, int>> (
+                               Expression.Convert (p, typeof (int)), p).Compile ();
+
+                       Assert.AreEqual (42, c (new Kling (42)));
+               }
+
+               [Test]
+               public void ConvertStructWithImplicitOpToNullableInt ()
                {
                        var c = Expression.Convert (Expression.Parameter (typeof (Kling), ""), typeof (int?));
                        Assert.AreEqual (typeof (int?), c.Type);
@@ -283,6 +305,17 @@ namespace MonoTests.System.Linq.Expressions {
                        Assert.IsNotNull (c.Method);
                }
 
+               [Test]
+               [Category ("NotWorking")]
+               public void ConvertNullableStructWithImplicitOpToNullableInt ()
+               {
+                       var c = Expression.Convert (Expression.Parameter (typeof (Kling?), ""), typeof (int?));
+                       Assert.AreEqual (typeof (int?), c.Type);
+                       Assert.IsTrue (c.IsLifted);
+                       Assert.IsTrue (c.IsLiftedToNull);
+                       Assert.IsNotNull (c.Method);
+               }
+
                [Test]
                public void CompiledBoxing ()
                {
@@ -318,6 +351,34 @@ namespace MonoTests.System.Linq.Expressions {
                        Assert.AreEqual (b, foo);
                }
 
+               [Test]
+               [Category ("NotWorking")]
+               public void CompileNotNullableToNullable ()
+               {
+                       var p = Expression.Parameter (typeof (int), "i");
+                       var c = Expression.Lambda<Func<int, int?>> (
+                               Expression.Convert (p, typeof (int?)), p).Compile ();
+
+                       Assert.AreEqual ((int?) 0, c (0));
+                       Assert.AreEqual ((int?) 42, c (42));
+               }
+
+               [Test]
+               [Category ("NotWorking")]
+               public void CompileNullableToNotNullable ()
+               {
+                       var p = Expression.Parameter (typeof (int?), "i");
+                       var c = Expression.Lambda<Func<int?, int>> (
+                               Expression.Convert (p, typeof (int)), p).Compile ();
+
+                       Assert.AreEqual (0, c ((int?) 0));
+                       Assert.AreEqual (42, c ((int?) 42));
+
+                       Action a = () => c (null);
+
+                       a.AssertThrows (typeof (InvalidOperationException));
+               }
+
                [Test]
                public void CompiledConvertToSameType ()
                {
index afd05b7607065d82276bc86325adcec9e48c7022..bf388f009b08347df8feda5e76d0ace8d4f66d7b 100644 (file)
@@ -275,5 +275,16 @@ namespace MonoTests.System.Linq.Expressions
                {
                        return Expression.Constant (t);
                }
+
+               public static void AssertThrows (this Action action, Type type)
+               {
+                       try {
+                               action ();
+                               Assert.Fail ();
+                       } catch (Exception e) {
+                               if (e.GetType () != type)
+                                       Assert.Fail ();
+                       }
+               }
        }
 }
index b4c78b7741e00afcb8d8416db75a36466a37fd97..39a5752169efd73bf33fec05bda2d0cd7a1117cd 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-30  Jb Evain  <jbevain@novell.com>
+
+       * EnumerableTest.cs: tests for average on int and long.
+
 2008-04-22  Leonid Freydovich <leonidf@mainsoft.com>
 
        * QueryableProviderTest.cs: add simple test for Queryable.
index 9b22a0ba7aae5ebea5f2dc475203dca3a812963c..b8fcbaf08afbe6c2200ed48a509b4ebd2b2cadad 100644 (file)
@@ -234,25 +234,111 @@ namespace MonoTests.System.Linq {
 
                        Assert.AreEqual (typeof (int []), array.GetType ());
                }
-                
-                [Test]
-                public void TestOrderBy ()
-                {
-                        int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
-                        var q = from i in array
-                                orderby i
-                                select i;
-                        AssertIsOrdered (q);
-                }
-                
-                static void AssertIsOrdered (IEnumerable<int> e)
-                {
-                        int f = int.MinValue;
-                        foreach(int i in e) {
-                                Assert.IsTrue (f <= i);
-                                f = i;
-                        }
-                }
+
+               [Test]
+               public void TestAverageOnInt32 ()
+               {
+                       Assert.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }).Average ());
+               }
+
+               [Test]
+               public void TestAverageOnInt64 ()
+               {
+                       Assert.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }).Average ());
+               }
+
+               [Test]
+               public void TestOrderBy ()
+               {
+                               int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
+                               var q = from i in array
+                                               orderby i
+                                               select i;
+                               AssertIsOrdered (q);
+               }
+
+               class Baz {
+                       string name;
+                       int age;
+
+                       public string Name
+                       {
+                               get {
+                                       if (string.IsNullOrEmpty (name))
+                                               return Age.ToString ();
+
+                                       return name + " (" + Age + ")";
+                               }
+                       }
+
+                       public int Age
+                       {
+                               get { return age + 1; }
+                       }
+
+                       public Baz (string name, int age)
+                       {
+                               this.name = name;
+                               this.age = age;
+                       }
+
+                       public override int GetHashCode ()
+                       {
+                               return this.Age ^ this.Name.GetHashCode ();
+                       }
+
+                       public override bool Equals (object obj)
+                       {
+                               Baz b = obj as Baz;
+                               if (b == null)
+                                       return false;
+
+                               return b.Age == this.Age && b.Name == this.Name;
+                       }
+
+                       public override string ToString ()
+                       {
+                               return this.Name;
+                       }
+               }
+
+               static IEnumerable<Baz> CreateBazCollection ()
+               {
+                       return new [] {
+                               new Baz ("jb", 25),
+                               new Baz ("ana", 20),
+                               new Baz ("reg", 28),
+                               new Baz ("ro", 25),
+                               new Baz ("jb", 7),
+                       };
+               }
+
+               [Test]
+               public void TestOrderByAgeAscendingTheByNameDescending ()
+               {
+                       var q = from b in CreateBazCollection ()
+                                       orderby b.Age ascending, b.Name descending
+                                       select b;
+
+                       var expected = new [] {
+                               new Baz ("jb", 7),
+                               new Baz ("ana", 20),
+                               new Baz ("ro", 25),
+                               new Baz ("jb", 25),
+                               new Baz ("reg", 28),
+                       };
+
+                       AssertAreSame (expected, q);
+               }
+
+               static void AssertIsOrdered (IEnumerable<int> e)
+               {
+                               int f = int.MinValue;
+                               foreach(int i in e) {
+                                               Assert.IsTrue (f <= i);
+                                               f = i;
+                               }
+               }
 
                static void AssertAreSame<T> (IEnumerable<T> expected, IEnumerable<T> actual)
                {
index 467d1aac3ffb6dca4361645882fccf3489ca8a28..9006479b2fa10672747a0edc289410b8dfc5cc94 100644 (file)
-using System;\r
-using System.Text;\r
-using System.Collections;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Linq.Expressions;\r
-using System.Reflection;\r
-using NUnit.Framework;\r
-\r
-\r
-namespace MonoTests.System.Linq\r
-{\r
-\r
-       [TestFixture]\r
-       public class QueryableProviderTest\r
-       {\r
-               QueryProvider _provider;\r
-\r
-               Query<int> _src;\r
-\r
-               int [] _array = { 1, 2, 3 };\r
-               int [] _otherArray = { 0, 2 };\r
-\r
-               public QueryableProviderTest ()\r
-               {\r
-                       _provider = new QueryProvider ();\r
-                       _src = new Query<int> (_provider, _array);\r
-\r
-               }\r
-\r
-               [SetUp]\r
-               public void MyTestCleanup ()\r
-               {\r
-                       _provider.Init ();\r
-               }\r
-\r
-               [Test]\r
-               public void TestAggregate ()\r
-               {\r
-                       _src.Aggregate<int> ((n, m) => n + m);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-\r
-               }\r
-\r
-               [Test]\r
-               public void TestAll ()\r
-               {\r
-                       _src.All<int> ((n) => true);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestAny ()\r
-               {\r
-                       _src.Any<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestAverage ()\r
-               {\r
-                       _src.Average<int> ((n) => n);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestCast ()\r
-               {\r
-                       _src.Cast<int> ();\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestConcat ()\r
-               {\r
-                       _src.Concat<int> (_otherArray);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestContains ()\r
-               {\r
-                       _src.Contains<int> (3);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-\r
-               [Test]\r
-               public void TestCount ()\r
-               {\r
-                       _src.Count<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestDefaultIfEmpty ()\r
-               {\r
-                       _src.DefaultIfEmpty<int> (0);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestDistinct ()\r
-               {\r
-                       _src.Distinct<int> ();\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestElementAt ()\r
-               {\r
-                       _src.ElementAt<int> (1);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestElementAtOrDefault ()\r
-               {\r
-                       _src.ElementAtOrDefault<int> (1);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestExcept ()\r
-               {\r
-                       _src.Except<int> (_otherArray);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestFirst ()\r
-               {\r
-                       _src.First<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestFirstOrDefault ()\r
-               {\r
-                       _src.FirstOrDefault<int> ((n) => n > 1);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestGroupBy ()\r
-               {\r
-                       _src.GroupBy<int, bool> ((n) => n > 2);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestGroupJoin ()\r
-               {\r
-                       _src.GroupJoin<int, int, bool, int> (_otherArray, (n) => n > 1, (n) => n > 1, (n, col) => n);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestIntersect ()\r
-               {\r
-                       _src.Intersect<int> (_otherArray);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestJoin ()\r
-               {\r
-                       _src.Join<int, int, int, int> (_otherArray, (n) => n, (n => n), (n, m) => n + m);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestLast ()\r
-               {\r
-                       _src.Last<int> ((n) => n > 1);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestLastOrDefault ()\r
-               {\r
-                       _src.LastOrDefault<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestLongCount ()\r
-               {\r
-                       _src.LongCount<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestMax ()\r
-               {\r
-                       _src.Max<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestMin ()\r
-               {\r
-                       _src.Min<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestOfType ()\r
-               {\r
-                       _src.OfType<int> ();\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestOrderBy ()\r
-               {\r
-                       _src.OrderBy<int, bool> ((n) => n > 1);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestOrderByDescending ()\r
-               {\r
-                       _src.OrderByDescending<int, bool> ((n) => n > 1);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestReverse ()\r
-               {\r
-                       _src.Reverse<int> ();\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSelect ()\r
-               {\r
-                       _src.Select<int, int> ((n) => n);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSelectMany ()\r
-               {\r
-                       _src.SelectMany<int, int> ((n) => new int [] { n });\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSequenceEqual ()\r
-               {\r
-                       _src.SequenceEqual<int> (_otherArray);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSingle ()\r
-               {\r
-                       (new Query<int> (_provider, new int [] { 1 })).Single<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSingleOrDefault ()\r
-               {\r
-                       (new Query<int> (_provider, new int [] { 1 })).SingleOrDefault<int> ();\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSkip ()\r
-               {\r
-                       _src.Skip<int> (1);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSkipWhile ()\r
-               {\r
-                       _src.SkipWhile<int> ((n) => n > 1);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestSum ()\r
-               {\r
-                       _src.Sum<int> ((n) => n);\r
-                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestTake ()\r
-               {\r
-                       _src.Take<int> (3);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-\r
-               [Test]\r
-               public void TestTakeWhile ()\r
-               {\r
-                       _src.TakeWhile<int> ((n) => n < 2);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestThenBy ()\r
-               {\r
-                       _src.ThenBy<int, bool> ((n) => n < 2);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestThenByDescending ()\r
-               {\r
-                       _src.ThenByDescending<int, bool> ((n) => n < 2);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestUnion ()\r
-               {\r
-                       _src.Union<int> (_otherArray);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               [Test]\r
-               public void TestWhere ()\r
-               {\r
-                       _src.Where<int> ((n) => true);\r
-                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);\r
-               }\r
-\r
-               public class Query<T> : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable, IOrderedQueryable<T>, IOrderedQueryable\r
-               {\r
-                       IQueryProvider provider;\r
-\r
-                       Expression expression;\r
-\r
-                       IEnumerable<T> _context;\r
-\r
-                       public Query (IQueryProvider provider, IEnumerable<T> context)\r
-                       {\r
-                               _context = context;\r
-                               this.provider = provider;\r
-                               this.expression = Expression.Constant (this);\r
-                       }\r
-\r
-                       Expression IQueryable.Expression\r
-                       {\r
-\r
-                               get { return this.expression; }\r
-\r
-                       }\r
-\r
-\r
-\r
-                       Type IQueryable.ElementType\r
-                       {\r
-\r
-                               get { return typeof (T); }\r
-\r
-                       }\r
-\r
-\r
-                       IQueryProvider IQueryable.Provider\r
-                       {\r
-\r
-                               get { return this.provider; }\r
-\r
-                       }\r
-\r
-\r
-                       public IEnumerator<T> GetEnumerator ()\r
-                       {\r
-                               throw new NotImplementedException ();\r
-                       }\r
-\r
-                       IEnumerator IEnumerable.GetEnumerator ()\r
-                       {\r
-                               throw new NotImplementedException ();\r
-                       }\r
-\r
-               }\r
-\r
-               public enum StatusEnum { NotInitilized, Execute, CreateQuery }\r
-\r
-               public class QueryProvider : IQueryProvider\r
-               {\r
-\r
-                       private StatusEnum _status = StatusEnum.NotInitilized;\r
-\r
-                       public StatusEnum Status\r
-                       {\r
-                               get { return _status; }\r
-                               set { _status = value; }\r
-                       }\r
-\r
-                       public void Init ()\r
-                       {\r
-                               _status = StatusEnum.NotInitilized;\r
-                       }\r
-\r
-                       public QueryProvider ()\r
-                       {\r
-                               Init ();\r
-                       }\r
-\r
-                       #region IQueryProvider Members\r
-\r
-                       IQueryable<S> IQueryProvider.CreateQuery<S> (Expression expression)\r
-                       {\r
-                               Status = StatusEnum.CreateQuery;\r
-                               return null;\r
-                       }\r
-\r
-                       IQueryable IQueryProvider.CreateQuery (Expression expression)\r
-                       {\r
-                               Status = StatusEnum.CreateQuery;\r
-                               return null;\r
-\r
-                       }\r
-\r
-                       S IQueryProvider.Execute<S> (Expression expression)\r
-                       {\r
-                               Status = StatusEnum.Execute;\r
-                               return default (S);\r
-                       }\r
-\r
-\r
-\r
-                       object IQueryProvider.Execute (Expression expression)\r
-                       {\r
-                               Status = StatusEnum.Execute;\r
-                               return null;\r
-\r
-                       }\r
-\r
-                       #endregion\r
-               }\r
-       }\r
-}\r
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using NUnit.Framework;
+
+
+namespace MonoTests.System.Linq
+{
+
+       [TestFixture]
+       public class QueryableProviderTest
+       {
+               QueryProvider _provider;
+
+               Query<int> _src;
+
+               int [] _array = { 1, 2, 3 };
+               int [] _otherArray = { 0, 2 };
+
+               public QueryableProviderTest ()
+               {
+                       _provider = new QueryProvider ();
+                       _src = new Query<int> (_provider, _array);
+
+               }
+
+               [SetUp]
+               public void MyTestCleanup ()
+               {
+                       _provider.Init ();
+               }
+
+               [Test]
+               public void TestAggregate ()
+               {
+                       _src.Aggregate<int> ((n, m) => n + m);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+
+               }
+
+               [Test]
+               public void TestAll ()
+               {
+                       _src.All<int> ((n) => true);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestAny ()
+               {
+                       _src.Any<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestAverage ()
+               {
+                       _src.Average<int> ((n) => n);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestCast ()
+               {
+                       _src.Cast<int> ();
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestConcat ()
+               {
+                       _src.Concat<int> (_otherArray);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestContains ()
+               {
+                       _src.Contains<int> (3);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+
+               [Test]
+               public void TestCount ()
+               {
+                       _src.Count<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestDefaultIfEmpty ()
+               {
+                       _src.DefaultIfEmpty<int> (0);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestDistinct ()
+               {
+                       _src.Distinct<int> ();
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestElementAt ()
+               {
+                       _src.ElementAt<int> (1);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestElementAtOrDefault ()
+               {
+                       _src.ElementAtOrDefault<int> (1);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestExcept ()
+               {
+                       _src.Except<int> (_otherArray);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestFirst ()
+               {
+                       _src.First<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestFirstOrDefault ()
+               {
+                       _src.FirstOrDefault<int> ((n) => n > 1);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestGroupBy ()
+               {
+                       _src.GroupBy<int, bool> ((n) => n > 2);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestGroupJoin ()
+               {
+                       _src.GroupJoin<int, int, bool, int> (_otherArray, (n) => n > 1, (n) => n > 1, (n, col) => n);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestIntersect ()
+               {
+                       _src.Intersect<int> (_otherArray);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestJoin ()
+               {
+                       _src.Join<int, int, int, int> (_otherArray, (n) => n, (n => n), (n, m) => n + m);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestLast ()
+               {
+                       _src.Last<int> ((n) => n > 1);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestLastOrDefault ()
+               {
+                       _src.LastOrDefault<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestLongCount ()
+               {
+                       _src.LongCount<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestMax ()
+               {
+                       _src.Max<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestMin ()
+               {
+                       _src.Min<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestOfType ()
+               {
+                       _src.OfType<int> ();
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestOrderBy ()
+               {
+                       _src.OrderBy<int, bool> ((n) => n > 1);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestOrderByDescending ()
+               {
+                       _src.OrderByDescending<int, bool> ((n) => n > 1);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestReverse ()
+               {
+                       _src.Reverse<int> ();
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestSelect ()
+               {
+                       _src.Select<int, int> ((n) => n);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestSelectMany ()
+               {
+                       _src.SelectMany<int, int> ((n) => new int [] { n });
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestSequenceEqual ()
+               {
+                       _src.SequenceEqual<int> (_otherArray);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestSingle ()
+               {
+                       (new Query<int> (_provider, new int [] { 1 })).Single<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestSingleOrDefault ()
+               {
+                       (new Query<int> (_provider, new int [] { 1 })).SingleOrDefault<int> ();
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestSkip ()
+               {
+                       _src.Skip<int> (1);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestSkipWhile ()
+               {
+                       _src.SkipWhile<int> ((n) => n > 1);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestSum ()
+               {
+                       _src.Sum<int> ((n) => n);
+                       Assert.AreEqual (StatusEnum.Execute, _provider.Status);
+               }
+
+               [Test]
+               public void TestTake ()
+               {
+                       _src.Take<int> (3);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+
+               [Test]
+               public void TestTakeWhile ()
+               {
+                       _src.TakeWhile<int> ((n) => n < 2);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestThenBy ()
+               {
+                       _src.ThenBy<int, bool> ((n) => n < 2);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestThenByDescending ()
+               {
+                       _src.ThenByDescending<int, bool> ((n) => n < 2);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestUnion ()
+               {
+                       _src.Union<int> (_otherArray);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               [Test]
+               public void TestWhere ()
+               {
+                       _src.Where<int> ((n) => true);
+                       Assert.AreEqual (StatusEnum.CreateQuery, _provider.Status);
+               }
+
+               public class Query<T> : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable, IOrderedQueryable<T>, IOrderedQueryable
+               {
+                       IQueryProvider provider;
+
+                       Expression expression;
+
+                       IEnumerable<T> _context;
+
+                       public Query (IQueryProvider provider, IEnumerable<T> context)
+                       {
+                               _context = context;
+                               this.provider = provider;
+                               this.expression = Expression.Constant (this);
+                       }
+
+                       Expression IQueryable.Expression
+                       {
+
+                               get { return this.expression; }
+
+                       }
+
+
+
+                       Type IQueryable.ElementType
+                       {
+
+                               get { return typeof (T); }
+
+                       }
+
+
+                       IQueryProvider IQueryable.Provider
+                       {
+
+                               get { return this.provider; }
+
+                       }
+
+
+                       public IEnumerator<T> GetEnumerator ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       IEnumerator IEnumerable.GetEnumerator ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+               }
+
+               public enum StatusEnum { NotInitilized, Execute, CreateQuery }
+
+               public class QueryProvider : IQueryProvider
+               {
+
+                       private StatusEnum _status = StatusEnum.NotInitilized;
+
+                       public StatusEnum Status
+                       {
+                               get { return _status; }
+                               set { _status = value; }
+                       }
+
+                       public void Init ()
+                       {
+                               _status = StatusEnum.NotInitilized;
+                       }
+
+                       public QueryProvider ()
+                       {
+                               Init ();
+                       }
+
+                       #region IQueryProvider Members
+
+                       IQueryable<S> IQueryProvider.CreateQuery<S> (Expression expression)
+                       {
+                               Status = StatusEnum.CreateQuery;
+                               return null;
+                       }
+
+                       IQueryable IQueryProvider.CreateQuery (Expression expression)
+                       {
+                               Status = StatusEnum.CreateQuery;
+                               return null;
+
+                       }
+
+                       S IQueryProvider.Execute<S> (Expression expression)
+                       {
+                               Status = StatusEnum.Execute;
+                               return default (S);
+                       }
+
+
+
+                       object IQueryProvider.Execute (Expression expression)
+                       {
+                               Status = StatusEnum.Execute;
+                               return null;
+
+                       }
+
+                       #endregion
+               }
+       }
+}
index e5762e8348f8242a1deb4fb9503ea0377074ae6e..2ee161f8ddd54808ff4b7494a97018d17f5fe01e 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Marek Habersack  <mhabersack@novell.com>
+
+       * SiteMapDataSource.cs: when no starting node is found, return
+       null instead of Provider.RootNode. Fixes bug #323994
+
 2008-04-24  Marek Habersack  <mhabersack@novell.com>
 
        * SqlDataSource.cs: raise the DataSourceChangedEvent when setting
index c0b81bf64fb8afdc4692faaab7a8d2b491e4d665..c97ea2f4c1564c990299c295c3f686deba1956ba 100644 (file)
@@ -199,7 +199,7 @@ namespace System.Web.UI.WebControls
                                starting_node = Provider.RootNode;
 
                        if (starting_node == null)
-                               return Provider.RootNode;
+                               return null;
                        
                        int i;
                        if (StartingNodeOffset < 0) {
index d84ec406244200738f424c581b77a62d8d4445d2..65d3af4b754929cb65552c0e3ccae140beef019d 100644 (file)
@@ -1,3 +1,20 @@
+2008-04-30  Marek Habersack  <mhabersack@novell.com>
+
+       * HttpApplication.cs: when the Start method is called in a new
+       thread, the thread's culture and ui culture are set to their
+       defaults, thus ignoring whatever their values were in the parent
+       thread. This is now fixed by passing an array containing the
+       culture values to the Start method, so that the new thread can be
+       properly initialized. Fixes bug #323566
+
+       * SiteMapNode.cs: the implicitResourceKey parameter to one of the
+       constructors sets the value of the ResourceKey property.
+       GetImplicitResourceString uses the provider's ResourceKey as the
+       global resource object key and the node's ResourceKey to construct
+       the resource name. Fixes bug #323994
+       ResourceKey setter throws an InvalidOperationException now, when
+       the node is read-only.
+
 2008-04-29  Marek Habersack  <mhabersack@novell.com>
 
        * HttpException.cs: safe guard against context being null in
index 58be0739dd609aad831462e78bb8fc9a04aa2765..c311d1e6c62c66d52504e223d61ae96dddde61b2 100644 (file)
@@ -1391,6 +1391,13 @@ namespace System.Web {
 
                void Start (object x)
                {
+                       CultureInfo[] cultures = x as CultureInfo[];
+                       if (cultures != null && cultures.Length == 2) {
+                               Thread ct = Thread.CurrentThread;
+                               ct.CurrentCulture = cultures [0];
+                               ct.CurrentUICulture = cultures [1];
+                       }
+                       
                        try {
                                InitOnce (true);
                        } catch (Exception e) {
@@ -1510,6 +1517,10 @@ namespace System.Web {
                        
                        begin_iar = new AsyncRequestState (done, cb, extraData);
 
+                       CultureInfo[] cultures = new CultureInfo [2];
+                       cultures [0] = Thread.CurrentThread.CurrentCulture;
+                       cultures [1] = Thread.CurrentThread.CurrentUICulture;
+                       
 #if TARGET_JVM
                        if (true)
 #else
@@ -1517,7 +1528,7 @@ namespace System.Web {
 #endif
                                Start (null);
                        else
-                               ThreadPool.QueueUserWorkItem (new WaitCallback (Start), null);
+                               ThreadPool.QueueUserWorkItem (new WaitCallback (Start), cultures);
                        
                        return begin_iar;
                }
index 07608b87d588303661fbd2a93882d66453578599..27692edde6b63f5e374bf94ac6900fce7405a364 100644 (file)
@@ -68,7 +68,7 @@ namespace System.Web {
                        this.roles = roles;
                        this.attributes = attributes;
                        this.resourceKeys = explicitResourceKeys;
-                       this.implicitResourceKey = implicitResourceKey;
+                       this.resourceKey = implicitResourceKey;
                }
 
                public SiteMapDataSourceView GetDataSourceView (SiteMapDataSource owner, string viewName)
@@ -224,21 +224,15 @@ namespace System.Web {
                        if (attributeName == null)
                                throw new ArgumentNullException ("attributeName");
 
-                       if (String.IsNullOrEmpty (implicitResourceKey))
+                       string resourceKey = ResourceKey;
+                       if (String.IsNullOrEmpty (resourceKey))
                                return null;
 
                        try {
-                               string reskey = provider.ResourceKey;
-
-                               if (!String.IsNullOrEmpty (reskey))
-                                       reskey = reskey + "." + implicitResourceKey + "." + attributeName;
-                               else
-                                       reskey = String.Concat (implicitResourceKey, ".", attributeName);
-                               object o = HttpContext.GetGlobalResourceObject ("Web.sitemap", reskey);
+                               object o = HttpContext.GetGlobalResourceObject (provider.ResourceKey, resourceKey + "." + attributeName);
                                if (o is string)
                                        return (string) o;
-                       }
-                       catch (MissingManifestResourceException) {
+                       } catch (MissingManifestResourceException) {
                        }
                        
                        return null;
@@ -398,7 +392,11 @@ namespace System.Web {
                
                public string ResourceKey {
                        get { return resourceKey; }
-                       set { resourceKey = value; }
+                       set {
+                               if (ReadOnly)
+                                       throw new InvalidOperationException ("The node is read-only.");
+                               resourceKey = value;
+                       }
                }
                
                public string Key { get { return key; } }
@@ -437,7 +435,6 @@ namespace System.Web {
                bool readOnly;
                string resourceKey;
                SiteMapNode parent;
-               string implicitResourceKey;
                SiteMapNodeCollection childNodes;
                #endregion
                
index 2e14b3d7ba700f4b9ad6e6e55e5e56bc0cf8f11b..64d7e34d8574361c91f69fb2e04047cad324e401 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * XElement.cs, XNode.cs : XNode.ReadFrom() should not reuse
+         XElement.Load() which may create wrapper XmlReader.
+
 2008-02-12  Atsushi Enomoto  <atsushi@ximian.com>
 
        * XElement.cs : Value is rather a value in XPath semantics than
index abddeb2a5d48f0deca5d868b4b3a0554d4299a5b..4726b650d671e87377192206e49950a744efc6e9 100644 (file)
@@ -396,7 +396,7 @@ namespace System.Xml.Linq
                        }
                }
 
-               static XElement LoadCore (XmlReader r, LoadOptions options)
+               internal static XElement LoadCore (XmlReader r, LoadOptions options)
                {
                        r.MoveToContent ();
                        if (r.NodeType != XmlNodeType.Element)
index d1aeecfa710636f292cfe63e13fcdce73815effc..5191bb1c5b7706b94385044d4db78c13f1fce4ac 100644 (file)
@@ -149,7 +149,7 @@ namespace System.Xml.Linq
                {
                        switch (r.NodeType) {
                        case XmlNodeType.Element:
-                               return XElement.Load (r, options);
+                               return XElement.LoadCore (r, options);
                        case XmlNodeType.Whitespace:
                        case XmlNodeType.SignificantWhitespace:
                        case XmlNodeType.Text:
index f0f17aa12f81f6e3fdadf015871c4c7d7ee8f6ef..bdc1c9d821e52da9280a4d827745d66155fd1404 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-30  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * XNodeReaderTest.cs : added CreateReader3().
+
 2008-02-12  Atsushi Enomoto  <atsushi@ximian.com>
 
        * XElementTest.cs : added test for Value (bug #360858).
index 7009d07653b431ea17505476eebc46ce66634f1b..020509d3911b062feaa35ba32c51dc23c0d229bb 100644 (file)
@@ -66,6 +66,22 @@ namespace MonoTests.System.Xml.Linq
                        Assert.AreEqual (xml.Replace ('\'', '"'), sw.ToString ());
                }
 
+               [Test] // almost identical to CreateReader1().
+               public void CreateReader3 ()
+               {
+                       string xml = "<root><foo a='v' /><bar></bar><baz>simple text<!-- comment --><mixed1 /><mixed2><![CDATA[cdata]]><?some-pi with-data ?></mixed2></baz></root>";
+                       XDocument doc = XDocument.Parse (xml, LoadOptions.PreserveWhitespace);
+                       XmlReader xr = doc.CreateReader ();
+                       StringWriter sw = new StringWriter ();
+                       XmlWriterSettings s = new XmlWriterSettings ();
+                       s.OmitXmlDeclaration = true;
+                       XmlWriter xw = XmlWriter.Create (sw, s);
+                       while (!xr.EOF)
+                               xw.WriteNode (xr, false);
+                       xw.Close ();
+                       Assert.AreEqual (xml.Replace ('\'', '"'), sw.ToString ());
+               }
+
                [Test]
                public void GetAttribute ()
                {
index f3ef19b3434d5c2748cc6bd772d0c6301def7a20..f733d959112f7f6cf6786b7701c4e76482827b9e 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * VBCodeGenerator.cs: Fixed generated code for abstract properties.
+
 2008-03-13  Rolf Bjarne Kvinge <RKvinge@novell.com> 
 
        * VBCodeGenerator.cs: Add quotes around the filename in ExternalSource
index 3c0ced37f0f61b78b2974b979bb9fb4b47baf17d..596746ad2e59ae7b2ae04a1620a0fb7321e08fb1 100644 (file)
@@ -920,18 +920,22 @@ namespace Microsoft.VisualBasic
                                ++Indent;
                                if (property.HasGet) {
                                        output.WriteLine ("Get");
-                                       ++Indent;
-                                       GenerateStatements (property.GetStatements);
-                                       --Indent;
-                                       output.WriteLine ("End Get");
+                                       if (!IsAbstract (property.Attributes)) {
+                                               ++Indent;
+                                               GenerateStatements (property.GetStatements);
+                                               --Indent;
+                                               output.WriteLine ("End Get");
+                                       }
                                }
 
                                if (property.HasSet) {
                                        output.WriteLine ("Set");
-                                       ++Indent;
-                                       GenerateStatements (property.SetStatements);
-                                       --Indent;
-                                       output.WriteLine ("End Set");
+                                       if (!IsAbstract (property.Attributes)) {
+                                               ++Indent;
+                                               GenerateStatements (property.SetStatements);
+                                               --Indent;
+                                               output.WriteLine ("End Set");
+                                       }
                                }
 
                                --Indent;
@@ -1735,6 +1739,11 @@ namespace Microsoft.VisualBasic
                        return baseType + "_" + property.Name;
                }
 
+               static bool IsAbstract (MemberAttributes attributes)
+               {
+                       return (attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract;
+               }
+
                private enum LineHandling
                {
                        InLine,
index 706c7947da4349150c15084b18ea3ebe71f011bd..66215ddae4984856ce1431ffbe7e81a8fe56b8ae 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Miguel de Icaza  <miguel@novell.com>
+
+       * WebPermission.cs (ToXml): To allow code that uses WebPermission
+       to be built. 
+
 2008-04-21 Gonzalo Paniagua Javier <gonzalo.mono@gmail.com>
 
        * HttpWebResponse.cs: do not check the disposed status for properties
index 7ba9342f28c7148601292824813578d6a0005b1f..e1254463c47392038787c2c11e7880763922c307 100644 (file)
@@ -227,10 +227,20 @@ namespace System.Net {
                        return root;
                }
 
-               [MonoTODO]
                private void ToXml (SecurityElement root, string childName, IEnumerator enumerator)
                {
-                       throw new NotImplementedException ();
+                       SecurityElement child = new SecurityElement (childName, null);
+
+                       root.AddChild (child);
+                       while (enumerator.MoveNext ()){
+                               WebPermissionInfo x = enumerator.Current as WebPermissionInfo;
+
+                               if (x == null) continue;
+
+                               SecurityElement uri = new SecurityElement ("URI");
+                               uri.AddAttribute ("uri", x.Info);
+                               child.AddChild (uri);
+                       }
                }
 
                public override void FromXml (SecurityElement securityElement)
@@ -260,7 +270,6 @@ namespace System.Net {
                        }
                }
 
-               [MonoTODO]
                private void FromXml (ArrayList endpoints, NetworkAccess access)
                {
                        throw new NotImplementedException ();
index b9fff779eaa40b426dd62be08dd84a6f65b5880b..d23c027f1fc373ea5bb3079e6393a5e3a2cc4327 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * CodeGeneratorFromTypeTest.cs: Added tests for static and abstract
+       property.
+
 2008-03-13  Rolf Bjarne Kvinge <RKvinge@novell.com> 
 
        * CodeGeneratorFromCompileUnitTest.cs: Added ExternalSourceTest.
index 6ad0803dfdff4d259ec7368050fcaa90b54c6541..fd9a3543cf4c4602ffb0e78d3319e64c15692cc1 100644 (file)
@@ -218,6 +218,42 @@ namespace MonoTests.Microsoft.VisualBasic
                                "End Class{0}", NewLine), code);
                }
 
+               [Test]
+               public void AbstractPropertyTest ()
+               {
+                       string code = GenerateAbstractProperty (Options);
+                       Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
+                               "Public MustInherit Class Test1{0}" +
+                               "    {0}" +
+#if NET_2_0
+                               "    Public MustOverride Property Name() As String{0}" +
+#else
+                               "    Public MustOverride Property Name As String{0}" +
+#endif
+                               "        Get{0}" +
+                               "        Set{0}" +
+                               "    End Property{0}" +
+                               "End Class{0}", NewLine), code);
+               }
+
+               [Test]
+               public void StaticPropertyTest ()
+               {
+                       string code = GenerateStaticProperty (Options);
+                       Assert.AreEqual (string.Format (CultureInfo.InvariantCulture,
+                               "Public Class Test1{0}" +
+                               "    {0}" +
+#if NET_2_0
+                               "    Public Shared WriteOnly Property Name() As String{0}" +
+#else
+                               "    Public Shared WriteOnly Property Name As String{0}" +
+#endif
+                               "        Set{0}" +
+                               "        End Set{0}" +
+                               "    End Property{0}" +
+                               "End Class{0}", NewLine), code);
+               }
+
                [Test]
                public override void PropertyMembersTypeTest1 ()
                {
index d0858f5aa97a12a833ffaad1922497ccedf420b1..7cb35d125d598ea3fc0e4b2e8c71905385a3d57a 100644 (file)
@@ -1,3 +1,9 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * ExecutorTest.cs: Use Assert.Ignore when ping is not available.
+       Avoid using ExpectedException in ExecWait test, and added link to
+       MS bug report. 
+
 2008-04-08  Jb Evain  <jbevain@novell.com>
 
        * CodeGeneratorFromTypeTestBase.cs: add a generator for
index 56d62a51d3e4b1a5ff2ca7c3e62d1b7ea0afec2f..e6e0881944ce134f8ef871b395742c67e97d7843 100644 (file)
@@ -35,11 +35,11 @@ using System.IO;
 using System.Runtime.InteropServices;
 using System.Security.Principal;
 
-namespace MonoTests.System.CodeDom.Compiler {
-
+namespace MonoTests.System.CodeDom.Compiler
+{
        [TestFixture]
-       public class ExecutorTest {
-
+       public class ExecutorTest
+       {
                private bool posix;
                private bool cmdNotFound;
                private int errcode;
@@ -93,26 +93,36 @@ namespace MonoTests.System.CodeDom.Compiler {
                public void ExecWait_NullTempFileCollection ()
                {
                        if (cmdNotFound)
-                               throw new NullReferenceException ();
+                               Assert.Ignore ("ping command not found.");
+
                        Executor.ExecWait (cmd, null);
                }
 
                [Test]
-               [ExpectedException (typeof (ExternalException))]
-               [Category ("NotWorking")]
+               [Category ("NotWorking")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=341293
                public void ExecWait ()
                {
                        if (cmdNotFound)
-                               return;
-                       // why does it fail ? any case that works ?
-                       Executor.ExecWait (cmd, tfc);
+                               Assert.Ignore ("ping command not found.");
+
+                       try {
+                               Executor.ExecWait (cmd, new TempFileCollection ());
+                               Assert.Fail ("#1");
+                       } catch (ExternalException ex) {
+                               // Cannot execute a program. The command being executed was .
+                               Assert.AreEqual (typeof (ExternalException), ex.GetType (), "#2");
+                               Assert.AreEqual (2, ex.ErrorCode, "#3");
+                               Assert.IsNull (ex.InnerException, "#4");
+                               Assert.IsNotNull (ex.Message, "#5");
+                       }
                }
 
                [Test]
                public void ExecWaitWithCapture ()
                {
                        if (cmdNotFound)
-                               return;
+                               Assert.Ignore ("ping command not found.");
+
                        string output = null;
                        string error = null;
                        TempFileCollection tfc = new TempFileCollection ();
@@ -128,7 +138,8 @@ namespace MonoTests.System.CodeDom.Compiler {
                public void ExecWaitWithCapture_CurrentDir ()
                {
                        if (cmdNotFound)
-                               return;
+                               Assert.Ignore ("ping command not found.");
+
                        string output = null;
                        string error = null;
                        TempFileCollection tfc = new TempFileCollection ();
@@ -145,7 +156,8 @@ namespace MonoTests.System.CodeDom.Compiler {
                public void ExecWaitWithCapture_Token ()
                {
                        if (cmdNotFound)
-                               return;
+                               Assert.Ignore ("ping command not found.");
+
                        string output = null;
                        string error = null;
                        TempFileCollection tfc = new TempFileCollection ();
@@ -161,7 +173,8 @@ namespace MonoTests.System.CodeDom.Compiler {
                public void ExecWaitWithCapture_Token_CurrentDir ()
                {
                        if (cmdNotFound)
-                               return;
+                               Assert.Ignore ("ping command not found.");
+
                        string output = null;
                        string error = null;
                        TempFileCollection tfc = new TempFileCollection ();
index adb4fe5a14c5b7640c881f430c0570d490cc8976..f3deff1d920a481e818e2beccc31fdf8e8e1b990 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * ComponentConverterTests.cs: Allow test to be compiled using csc 1.x.
+
 2008-04-16  Marek Habersack  <mhabersack@novell.com>
 
        * ComponentConverterTests.cs: added tests for
index 3f4451c6542102c3987a1bbb63046ee664aaa3d0..74e300b32727b4abe6a2f91de62120149bd6d109 100644 (file)
@@ -24,7 +24,7 @@ namespace MonoTests.System.ComponentModel
                public void DataSetConversions ()
                {
                        TypeConverter converter = TypeDescriptor.GetConverter (typeof (DataSet));
-                       Assert.AreEqual (typeof (global::System.ComponentModel.ComponentConverter), converter != null ? converter.GetType () : null, "A1");
+                       Assert.AreEqual (typeof (ComponentConverter), converter != null ? converter.GetType () : null, "A1");
 
                        DataSet ds = new DataSet ();
                        string s = (string) converter.ConvertTo (null, CultureInfo.InvariantCulture, ds, typeof (string));
index 171e695df5143089f4c5cfe7cb603c70f36fd48c..5291917e4e1311799e8a8c7de7cff6b53d815fbe 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>>
+
+       * corlib_test.dll.sources: Added ConstructorOnTypeBuilderInstTest.cs.
+
 2008-04-26  Gert Driesen  <drieseng@users.sourceforge.net>
 
        * corlib_test.dll.sources: Added MethodOnTypeBuilderInstTest.cs.
index 84bad6e0489331b87c62405b10bb3ffe18f39574..0ab4bd671dcd7d4518fb2994f4fff95eb0353880 100644 (file)
@@ -1,3 +1,29 @@
+2008-05-01  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * ConstructorBuilder.cs: Switch arguments for AORE.
+
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * ModuleBuilder.cs (DefineType): Do not perform lookup of in cache if
+       name is null to allow correct exception to be thrown (in TypeBuilder
+       ctor).
+       * TypeBuilder: Moved name argument check to TypeBuilder ctor. Modified
+       ArgumentException parameter names to match MS. Removed duplicate check
+       for data length from DefineInitializedData. Modified check_name to
+       only throw when first character is null char.
+       * ConstructorBuilder.cs (GetParameters): Throw NotSupportedException
+       (2.0) or InvalidOperationException (1.0) when type is not yet created
+       and we're not in compiler context. Return empty array when no
+       parameters are defined.
+       (MethodHandle): Always throw NotSupportedException.
+       (DefineParameter): Prevent NRE when parameters is null.
+       (GetCustomAttributes): When not in compiler context, always throw
+       NotSupportedException.
+       * ConstructorOnTypeBuilderInst.cs: Delegate to ConstructorBuilder
+       where possible. Fixed ContainsGenericParameters and IsGenericMethod
+       to always return false. In MethodBase.Invoke, throw an
+       InvalidOperationException instead of NIE.
+
 2008-04-26  Gert Driesen  <drieseng@users.sourceforge.net>
 
        * MethodOnTypeBuilderInst.cs: Added overrides for ReturnType and 
index 81fa281eb6d96adc08f3789908b65b82a2cea191..6297bff84bcd639346f410ffba4a76b8403bf9bb 100644 (file)
@@ -62,7 +62,8 @@ namespace System.Reflection.Emit {
                private Type[][] paramModOpt;
                private RefEmitPermissionSet[] permissions;
 
-               internal ConstructorBuilder (TypeBuilder tb, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt) {
+               internal ConstructorBuilder (TypeBuilder tb, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt)
+               {
                        attrs = attributes | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
                        call_conv = callingConvention;
                        if (parameterTypes != null) {
@@ -78,35 +79,49 @@ namespace System.Reflection.Emit {
                        this.paramModOpt = paramModOpt;
                        table_idx = get_next_table_index (this, 0x06, true);
 
-                       ((ModuleBuilder)tb.Module).RegisterToken (this, GetToken ().Token);
+                       ((ModuleBuilder) tb.Module).RegisterToken (this, GetToken ().Token);
                }
 
 #if NET_2_0
                [MonoTODO]
                public override CallingConventions CallingConvention {
-                       get { return call_conv; }
+                       get {
+                               return call_conv;
+                       }
                }
 #endif
                public bool InitLocals {
-                       get {return init_locals;}
-                       set {init_locals = value;}
+                       get {
+                               return init_locals;
+                       }
+                       set {
+                               init_locals = value;
+                       }
                }
 
                internal TypeBuilder TypeBuilder {
-                       get {return type;}
+                       get {
+                               return type;
+                       }
                }
                
-               public override MethodImplAttributes GetMethodImplementationFlags() {
+               public override MethodImplAttributes GetMethodImplementationFlags ()
+               {
                        return iattrs;
                }
-               public override ParameterInfo[] GetParameters() {
+
+               public override ParameterInfo[] GetParameters ()
+               {
+                       if (!type.is_created && !IsCompilerContext)
+                               throw not_created ();
+
                        if (parameters == null)
-                               return null;
+                               return new ParameterInfo [0];
 
                        ParameterInfo[] retval = new ParameterInfo [parameters.Length];
-                       for (int i = 0; i < parameters.Length; i++) {
-                               retval [i] = new ParameterInfo (pinfo == null ? null : pinfo [i+1], parameters [i], this, i + 1);
-                       }
+                       for (int i = 0; i < parameters.Length; i++)
+                               retval [i] = new ParameterInfo (pinfo == null ? null
+                                       : pinfo [i+1], parameters [i], this, i + 1);
 
                        return retval;
                }
@@ -119,39 +134,66 @@ namespace System.Reflection.Emit {
                        return parameters.Length;
                }
                
-               public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
+               public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+               {
                        throw not_supported ();
                }
-               public override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) {
+
+               public override object Invoke (BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
+               {
                        throw not_supported ();
                }
 
-               public override RuntimeMethodHandle MethodHandle { 
+               public override RuntimeMethodHandle MethodHandle {
+                       get {
+                               throw not_supported ();
+                       }
+               }
+
+               public override MethodAttributes Attributes {
+                       get {
+                               return attrs;
+                       }
+               }
+
+               public override Type ReflectedType {
+                       get {
+                               return type;
+                       }
+               }
+
+               public override Type DeclaringType {
                        get {
-                               return mhandle;
+                               return type;
                        }
                }
 
-               public override MethodAttributes Attributes { 
-                       get {return attrs;} 
+               public Type ReturnType {
+                       get {
+                               return null;
+                       }
                }
-               public override Type ReflectedType { get {return type;}}
-               public override Type DeclaringType { get {return type;}}
-               public Type ReturnType { get {return null;}}
-               public override string Name { 
-                       get {return (attrs & MethodAttributes.Static) != 0 ? ConstructorInfo.TypeConstructorName : ConstructorInfo.ConstructorName;}
+
+               public override string Name {
+                       get {
+                               return (attrs & MethodAttributes.Static) != 0 ? ConstructorInfo.TypeConstructorName : ConstructorInfo.ConstructorName;
+                       }
                }
+
                public string Signature {
-                       get {return "constructor signature";}
+                       get {
+                               return "constructor signature";
+                       }
                }
 
-               public void AddDeclarativeSecurity( SecurityAction action, PermissionSet pset) {
+               public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset)
+               {
                        if (pset == null)
                                throw new ArgumentNullException ("pset");
                        if ((action == SecurityAction.RequestMinimum) ||
                                (action == SecurityAction.RequestOptional) ||
                                (action == SecurityAction.RequestRefuse))
-                               throw new ArgumentOutOfRangeException ("Request* values are not permitted", "action");
+                               throw new ArgumentOutOfRangeException ("action", "Request* values are not permitted");
 
                        RejectIfCreated ();
 
@@ -172,9 +214,9 @@ namespace System.Reflection.Emit {
                        attrs |= MethodAttributes.HasSecurity;
                }
 
-               public ParameterBuilder DefineParameter(int iSequence, ParameterAttributes attributes, string strParamName)
+               public ParameterBuilder DefineParameter (int iSequence, ParameterAttributes attributes, string strParamName)
                {
-                       if ((iSequence < 1) || (iSequence > parameters.Length))
+                       if (iSequence < 1 || iSequence > GetParameterCount ())
                                throw new ArgumentOutOfRangeException ("iSequence");
                        if (type.is_created)
                                throw not_after_created ();
@@ -186,46 +228,52 @@ namespace System.Reflection.Emit {
                        return pb;
                }
 
-               public override bool IsDefined (Type attribute_type, bool inherit) {
+               public override bool IsDefined (Type attribute_type, bool inherit)
+               {
                        throw not_supported ();
                }
 
-               public override object [] GetCustomAttributes (bool inherit) {
+               public override object [] GetCustomAttributes (bool inherit)
+               {
                        /*
                         * On MS.NET, this always returns not_supported, but we can't do this
                         * since there would be no way to obtain custom attributes of 
                         * dynamically created ctors.
                         */
-                       if (type.is_created)
+                       if (type.is_created && IsCompilerContext)
                                return MonoCustomAttrs.GetCustomAttributes (this, inherit);
                        else
                                throw not_supported ();
                }
 
-               public override object [] GetCustomAttributes (Type attributeType, bool inherit) {
-                       if (type.is_created)
+               public override object [] GetCustomAttributes (Type attributeType, bool inherit)
+               {
+                       if (type.is_created && IsCompilerContext)
                                return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
                        else
                                throw not_supported ();
                }
 
-               public ILGenerator GetILGenerator () {
+               public ILGenerator GetILGenerator ()
+               {
                        return GetILGenerator (64);
                }
 
 #if NET_2_0
                public
 #else
-               internal 
+               internal
 #endif
-               ILGenerator GetILGenerator (int size) {
+               ILGenerator GetILGenerator (int size)
+               {
                        if (ilgen != null)
                                return ilgen;
                        ilgen = new ILGenerator (type.Module, ((ModuleBuilder)type.Module).GetTokenGenerator (), size);
                        return ilgen;
                }
 
-               public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
+               public void SetCustomAttribute (CustomAttributeBuilder customBuilder)
+               {
                        if (customBuilder == null)
                                throw new ArgumentNullException ("customBuilder");
 
@@ -252,7 +300,8 @@ namespace System.Reflection.Emit {
 #if NET_2_0
                [ComVisible (true)]
 #endif
-               public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
+               public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute)
+               {
                        if (con == null)
                                throw new ArgumentNullException ("con");
                        if (binaryAttribute == null)
@@ -260,21 +309,28 @@ namespace System.Reflection.Emit {
 
                        SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
                }
-               public void SetImplementationFlags( MethodImplAttributes attributes) {
+
+               public void SetImplementationFlags (MethodImplAttributes attributes)
+               {
                        if (type.is_created)
                                throw not_after_created ();
 
                        iattrs = attributes;
                }
-               public Module GetModule() {
+
+               public Module GetModule ()
+               {
                        return type.Module;
                }
-               public MethodToken GetToken() {
+
+               public MethodToken GetToken ()
+               {
                        return new MethodToken (0x06000000 | table_idx);
                }
 
                [MonoTODO]
-               public void SetSymCustomAttribute( string name, byte[] data) {
+               public void SetSymCustomAttribute (string name, byte[] data)
+               {
                        if (type.is_created)
                                throw not_after_created ();
                }
@@ -287,11 +343,13 @@ namespace System.Reflection.Emit {
                }
 #endif
 
-               public override string ToString() {
+               public override string ToString ()
+               {
                        return "ConstructorBuilder ['" + type.Name + "']";
                }
 
-               internal void fixup () {
+               internal void fixup ()
+               {
                        if (((attrs & (MethodAttributes.Abstract | MethodAttributes.PinvokeImpl)) == 0) && ((iattrs & (MethodImplAttributes.Runtime | MethodImplAttributes.InternalCall)) == 0)) {
                        if ((ilgen == null) || (ILGenerator.Mono_GetCurrentOffset (ilgen) == 0))
                                throw new InvalidOperationException ("Method '" + Name + "' does not have a method body.");
@@ -311,23 +369,44 @@ namespace System.Reflection.Emit {
                        }
                }
 
-               internal override int get_next_table_index (object obj, int table, bool inc) {
+               internal override int get_next_table_index (object obj, int table, bool inc)
+               {
                        return type.get_next_table_index (obj, table, inc);
                }
 
-               private void RejectIfCreated () {
+               private bool IsCompilerContext {
+                       get {
+                               ModuleBuilder mb = (ModuleBuilder) TypeBuilder.Module;
+                               AssemblyBuilder ab = (AssemblyBuilder) mb.Assembly;
+                               return ab.IsCompilerContext;
+                       }
+               }
+
+               private void RejectIfCreated ()
+               {
                        if (type.is_created)
                                throw new InvalidOperationException ("Type definition of the method is complete.");
                }
 
-               private Exception not_supported () {
+               private Exception not_supported ()
+               {
                        return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
                }
 
-               private Exception not_after_created () {
+               private Exception not_after_created ()
+               {
                        return new InvalidOperationException ("Unable to change after type has been created.");
                }
 
+               private Exception not_created ()
+               {
+#if NET_2_0
+                       return new NotSupportedException ("The type is not yet created.");
+#else
+                       return new InvalidOperationException ("The type is not yet created.");
+#endif
+               }
+
                void _ConstructorBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
                {
                        throw new NotImplementedException ();
index 1e807d9f218316a6a642e3a2b6bcae8b5d7f3798..ce65e07fd03b93dc18700a559255b502040d5b7c 100644 (file)
@@ -45,7 +45,8 @@ namespace System.Reflection.Emit
                ConstructorBuilder cb;
                #endregion
 
-               public ConstructorOnTypeBuilderInst (MonoGenericClass instantiation, ConstructorBuilder cb) {
+               public ConstructorOnTypeBuilderInst (MonoGenericClass instantiation, ConstructorBuilder cb)
+               {
                        this.instantiation = instantiation;
                        this.cb = cb;
                }
@@ -72,41 +73,49 @@ namespace System.Reflection.Emit
                        }
                }
 
-               public override bool IsDefined (Type attributeType, bool inherit) {
-                       throw new NotSupportedException ();
+               public override bool IsDefined (Type attributeType, bool inherit)
+               {
+                       return cb.IsDefined (attributeType, inherit);
                }
 
-               public override object [] GetCustomAttributes (bool inherit) {
-                       throw new NotSupportedException ();
+               public override object [] GetCustomAttributes (bool inherit)
+               {
+                       return cb.GetCustomAttributes (inherit);
                }
 
-               public override object [] GetCustomAttributes (Type attributeType, bool inherit) {
-                       throw new NotSupportedException ();
+               public override object [] GetCustomAttributes (Type attributeType, bool inherit)
+               {
+                       return cb.GetCustomAttributes (attributeType, inherit);
                }
 
                //
                // MethodBase members
                //
 
-               public override MethodImplAttributes GetMethodImplementationFlags() {
+               public override MethodImplAttributes GetMethodImplementationFlags ()
+               {
                        return cb.GetMethodImplementationFlags ();
                }
 
-               public override ParameterInfo[] GetParameters() {
-                       throw new NotImplementedException ();
+               public override ParameterInfo[] GetParameters ()
+               {
+                       return cb.GetParameters ();
                }
 
-               internal override int GetParameterCount () {
+               internal override int GetParameterCount ()
+               {
                        return cb.GetParameterCount ();
                }
 
-               public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
-                       throw new NotImplementedException ();
+               public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+               {
+                       return cb.Invoke (obj, invokeAttr, binder, parameters,
+                               culture);
                }
 
                public override RuntimeMethodHandle MethodHandle {
                        get {
-                               throw new NotImplementedException ();
+                               return cb.MethodHandle;
                        }
                }
 
@@ -122,14 +131,14 @@ namespace System.Reflection.Emit
                        }
                }
 
-               public override Type [] GetGenericArguments () {
-                       throw new NotImplementedException ();
+               public override Type [] GetGenericArguments ()
+               {
+                       return cb.GetGenericArguments ();
                }
 
                public override bool ContainsGenericParameters {
                        get {
-                               // FIXME:
-                               throw new NotImplementedException ();
+                               return false;
                        }
                }
 
@@ -141,7 +150,7 @@ namespace System.Reflection.Emit
 
                public override bool IsGenericMethod {
                        get {
-                               return true;
+                               return false;
                        }
                }
 
@@ -150,10 +159,11 @@ namespace System.Reflection.Emit
                //
 
                public override object Invoke (BindingFlags invokeAttr, Binder binder, object[] parameters,
-                                                                          CultureInfo culture) {
-                       throw new NotImplementedException ();
+                                                                          CultureInfo culture)
+               {
+                       throw new InvalidOperationException ();
                }
        }
 }
 
-#endif
+#endif\r
index caa042e0c1f5538e28084dd1347ef535df1ecdcc..b31d4d56a63d6104eddbdd99036dcfce26f371d4 100644 (file)
@@ -253,7 +253,7 @@ namespace System.Reflection.Emit {
                }
 
                private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packsize, int typesize) {
-                       if (name_cache.Contains (name))
+                       if (name != null && name_cache.Contains (name))
                                throw new ArgumentException ("Duplicate type name within an assembly.");
 
                        TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packsize, typesize, null);
index 48e25880a7c08c7bef5c3480b0e069795b26a3a5..23295fb27914dc6b5d95530c3f1367f136826a7d 100644 (file)
@@ -126,6 +126,8 @@ namespace System.Reflection.Emit
                        this.class_size = type_size;
                        this.packing_size = packing_size;
                        this.nesting_type = nesting_type;
+                               
+                       check_name ("fullname", name);
 
                        if (parent == null && (attr & TypeAttributes.Interface) != 0 && (attr & TypeAttributes.Abstract) == 0)
                                throw new InvalidOperationException ("Interface must be declared abstract.");
@@ -387,7 +389,6 @@ namespace System.Reflection.Emit
                private TypeBuilder DefineNestedType (string name, TypeAttributes attr, Type parent, Type[] interfaces,
                                                      PackingSize packsize, int typesize)
                {
-                       check_name ("name", name);
                        // Visibility must be NestedXXX
                        /* This breaks mcs
                        if (((attrs & TypeAttributes.VisibilityMask) == TypeAttributes.Public) ||
@@ -538,7 +539,7 @@ namespace System.Reflection.Emit
                                !((attributes & MethodAttributes.Abstract) != 0) || 
                                !((attributes & MethodAttributes.Virtual) != 0)) &&
                                !(((attributes & MethodAttributes.Static) != 0)))
-                               throw new ArgumentException ("attributes", "Interface method must be abstract and virtual.");
+                               throw new ArgumentException ("Interface method must be abstract and virtual.");
 
                        if (returnType == null)
                                returnType = pmodule.assemblyb.corlib_void_type;
@@ -582,9 +583,9 @@ namespace System.Reflection.Emit
                        check_name ("dllName", dllName);
                        check_name ("entryName", entryName);
                        if ((attributes & MethodAttributes.Abstract) != 0)
-                               throw new ArgumentException ("attributes", "PInvoke methods must be static and native and cannot be abstract.");
+                               throw new ArgumentException ("PInvoke methods must be static and native and cannot be abstract.");
                        if (IsInterface)
-                               throw new ArgumentException ("PInvoke methods cannot exist on interfaces.");            
+                               throw new ArgumentException ("PInvoke methods cannot exist on interfaces.");
                        check_not_created ();
 
                        MethodBuilder res 
@@ -652,7 +653,7 @@ namespace System.Reflection.Emit
                {
                        check_name ("fieldName", fieldName);
                        if (type == typeof (void))
-                               throw new ArgumentException ("type",  "Bad field type in defining field.");
+                               throw new ArgumentException ("Bad field type in defining field.");
                        check_not_created ();
 
                        FieldBuilder res = new FieldBuilder (this, fieldName, type, attributes, requiredCustomAttributes, optionalCustomAttributes);
@@ -1504,7 +1505,7 @@ namespace System.Reflection.Emit
                {
                        check_name ("name", name);
                        if (eventtype == null)
-                               throw new ArgumentNullException ("eventtype");
+                               throw new ArgumentNullException ("type");
                        check_not_created ();
 
                        EventBuilder res = new EventBuilder (this, name, attributes, eventtype);
@@ -1523,22 +1524,22 @@ namespace System.Reflection.Emit
                public FieldBuilder DefineInitializedData (string name, byte[] data, FieldAttributes attributes) {
                        if (data == null)
                                throw new ArgumentNullException ("data");
-                       if ((data.Length == 0) || (data.Length > 0x3f0000))
-                               throw new ArgumentException ("data", "Data size must be > 0 and < 0x3f0000");
 
                        FieldBuilder res = DefineUninitializedData (name, data.Length, attributes);
                        res.SetRVAData (data);
-
                        return res;
                }
 
                static int UnmanagedDataCount = 0;
                
                public FieldBuilder DefineUninitializedData (string name, int size, FieldAttributes attributes)
-               {
-                       check_name ("name", name);
+               {
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
+                       if (name.Length == 0)
+                               throw new ArgumentException ("Empty name is not legal", "name");
                        if ((size <= 0) || (size > 0x3f0000))
-                               throw new ArgumentException ("size", "Data size must be > 0 and < 0x3f0000");
+                               throw new ArgumentException ("Data size must be > 0 and < 0x3f0000");
                        check_not_created ();
 
                        string typeName = "$ArrayType$" + size;
@@ -1629,7 +1630,7 @@ namespace System.Reflection.Emit
                                throw new ArgumentNullException (argName);
                        if (name.Length == 0)
                                throw new ArgumentException ("Empty name is not legal", argName);
-                       if (name.IndexOf ((char)0) != -1)
+                       if (name [0] == ((char)0))
                                throw new ArgumentException ("Illegal name", argName);
                }
 
index 890b872174595d5185abb5b89ccae49b4fcddc40..37b53455e1dc471b5793bdf5d353df7983d4d55f 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * ParameterInfo.cs: Name must default to null if no ParameterBuilder
+       is supplied.
+
 2008-04-22  Zoltan Varga  <vargaz@gmail.com>
 
        * MonoGenericClass.cs (GetMethod): Construct a MethodOnTypeBuilderInst object
index c939b249bc61a4de5a33abe2a5670230fcbe46ea..045354633174f0ccbfa842dacd64e3fd03bcf989 100644 (file)
@@ -58,7 +58,7 @@ namespace System.Reflection
                                this.PositionImpl = pb.Position - 1;    // ParameterInfo.Position is zero-based
                                this.AttrsImpl = (ParameterAttributes) pb.Attributes;
                        } else {
-                               this.NameImpl = "";
+                               this.NameImpl = null;
                                this.PositionImpl = position - 1;
                                this.AttrsImpl = ParameterAttributes.None;
                        }
index 9b5cf11176edbb4095bf10b29dea9283bb58d620..099412abb865184ae93cb81c42e7519f1787efac 100644 (file)
@@ -1,3 +1,20 @@
+2008-04-30  Alan McGovern  <alan.mcgovern@gmail.com>
+
+       * SHA384Managed.cs: Inlined helper methods and made
+       some fields local vars. Gives about 1.70x faster performance.
+
+2008-04-30  Alan McGovern  <alan.mcgovern@gmail.com>
+
+       * SHA256Managed.cs: Inlined helper methods removed
+       unnecessary casts and made a field a local var.
+       Gives about 1.70x faster performance.
+
+2008-04-27  Alan McGovern  <alan.mcgovern@gmail.com>
+
+       * SHA1CryptoServiceProvider.cs: Performed loop unrolling and
+       re-rolling to reduce IL size significantly and improve
+       perf by over 30%.
+
 2008-04-27  Sebastien Pouliot  <sebastien@ximian.com>
 
        * SHA1CryptoServiceProvider.cs: Quick optimization to get better
index fbddda77f47ee9d0ab2f5c404af451790f737b1f..424ecbaf8f6e72764dbdbe07d6af27523f2e053c 100644 (file)
@@ -79,7 +79,7 @@ namespace System.Security.Cryptography {
                        }
 
                        for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
-                               ProcessBlock (rgb, start+i);
+                               ProcessBlock (rgb, (uint)(start+i));
                        }
 
                        if (size%BLOCK_SIZE_BYTES != 0) {
@@ -115,29 +115,18 @@ namespace System.Security.Cryptography {
                        _H[4] = 0xC3D2E1F0;
                }
 
-               private void ProcessBlock(byte[] inputBuffer, int inputOffset) 
+               private void ProcessBlock(byte[] inputBuffer, uint inputOffset) 
                {
                        uint a, b, c, d, e;
-                       int i;
 
                        count += BLOCK_SIZE_BYTES;
 
                        // abc removal would not work on the fields
                        uint[] _H = this._H;
                        uint[] buff = this.buff;
-                       for (i=0; i<16; i++) {
-                               buff[i] = ((uint)(inputBuffer[inputOffset+4*i]) << 24)
-                                       | ((uint)(inputBuffer[inputOffset+4*i+1]) << 16)
-                                       | ((uint)(inputBuffer[inputOffset+4*i+2]) <<  8)
-                                       | ((uint)(inputBuffer[inputOffset+4*i+3]));
-                       }
+                       InitialiseBuff(buff, inputBuffer, inputOffset);
+                       FillBuff(buff);
 
-                       uint zt;
-                       for (i=16; i<80; i++) {
-                               zt = buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16];
-                               buff[i] = ((zt << 1) | (zt >> 31));
-                       }
-               
                        a = _H[0];
                        b = _H[1];
                        c = _H[2];
@@ -146,261 +135,144 @@ namespace System.Security.Cryptography {
 
                        // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
                        // Possibly roll up if this changes.
-       
-                       // ---- Round 1 --------
-  
-                       e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[0];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[1];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[2];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[3];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[4];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[5];
-                       b = (b << 30) | (b >> 2);
 
-                       d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[6];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[7];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[8];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[9];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[10];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[11];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[12];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[13];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[14];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[15];
-                       b = (b << 30) | (b >> 2);
+                       // ---- Round 1 --------
+                       int i=0;
+                       while (i < 20)
+                       {
+                               e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[i];
+                               b = (b << 30) | (b >> 2);
 
-                       d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[16];
-                       a = (a << 30) | (a >> 2);
+                               d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[i+1];
+                               a = (a << 30) | (a >> 2);
 
-                       c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[17];
-                       e = (e << 30) | (e >> 2);
+                               c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[i+2];
+                               e = (e << 30) | (e >> 2);
 
-                       b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[18];
-                       d = (d << 30) | (d >> 2);
+                               b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[i+3];
+                               d = (d << 30) | (d >> 2);
 
-                       a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[19];
-                       c = (c << 30) | (c >> 2);
+                               a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[i+4];
+                               c = (c << 30) | (c >> 2);
+                               i += 5;
+                       }
 
                        // ---- Round 2 --------
-  
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[20];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[21];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[22];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[23];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[24];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[25];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[26];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[27];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[28];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[29];
-                       c = (c << 30) | (c >> 2);
+                       while (i < 40)
+                       {
+                               e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[i];
+                               b = (b << 30) | (b >> 2);
 
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[30];
-                       b = (b << 30) | (b >> 2);
+                               d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[i + 1];
+                               a = (a << 30) | (a >> 2);
 
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[31];
-                       a = (a << 30) | (a >> 2);
+                               c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[i + 2];
+                               e = (e << 30) | (e >> 2);
 
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[32];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[33];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[34];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[35];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[36];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[37];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[38];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[39];
-                       c = (c << 30) | (c >> 2);
+                               b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[i + 3];
+                               d = (d << 30) | (d >> 2);
 
+                               a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[i + 4];
+                               c = (c << 30) | (c >> 2);
+                               i += 5;
+                       }
+                  
                        // ---- Round 3 --------
-  
-                       e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[40];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[41];
-                       a = (a << 30) | (a >> 2);
+                       while (i < 60)
+                       {
+                               e += ((a << 5) | (a >> 27)) + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC + buff[i];
+                               b = (b << 30) | (b >> 2);
 
-                       c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[42];
-                       e = (e << 30) | (e >> 2);
+                               d += ((e << 5) | (e >> 27)) + ((a & b) | (a & c) | (b & c)) + 0x8F1BBCDC + buff[i + 1];
+                               a = (a << 30) | (a >> 2);
 
-                       b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[43];
-                       d = (d << 30) | (d >> 2);
+                               c += ((d << 5) | (d >> 27)) + ((e & a) | (e & b) | (a & b)) + 0x8F1BBCDC + buff[i + 2];
+                               e = (e << 30) | (e >> 2);
 
-                       a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[44];
-                       c = (c << 30) | (c >> 2);
+                               b += ((c << 5) | (c >> 27)) + ((d & e) | (d & a) | (e & a)) + 0x8F1BBCDC + buff[i + 3];
+                               d = (d << 30) | (d >> 2);
 
-                       e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[45];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[46];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[47];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[48];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[49];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[50];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[51];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[52];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[53];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[54];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[55];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[56];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[57];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[58];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[59];
-                       c = (c << 30) | (c >> 2);
+                               a += ((b << 5) | (b >> 27)) + ((c & d) | (c & e) | (d & e)) + 0x8F1BBCDC + buff[i + 4];
+                               c = (c << 30) | (c >> 2);
+                               i += 5;
+                       }
 
                        // ---- Round 4 --------
-  
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[60];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[61];
-                       a = (a << 30) | (a >> 2);
-
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[62];
-                       e = (e << 30) | (e >> 2);
-
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[63];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[64];
-                       c = (c << 30) | (c >> 2);
+                       while (i < 80)
+                       {
+                               e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[i];
+                               b = (b << 30) | (b >> 2);
 
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[65];
-                       b = (b << 30) | (b >> 2);
+                               d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[i + 1];
+                               a = (a << 30) | (a >> 2);
 
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[66];
-                       a = (a << 30) | (a >> 2);
+                               c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[i + 2];
+                               e = (e << 30) | (e >> 2);
 
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[67];
-                       e = (e << 30) | (e >> 2);
+                               b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[i + 3];
+                               d = (d << 30) | (d >> 2);
 
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[68];
-                       d = (d << 30) | (d >> 2);
-
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[69];
-                       c = (c << 30) | (c >> 2);
-
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[70];
-                       b = (b << 30) | (b >> 2);
-
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[71];
-                       a = (a << 30) | (a >> 2);
+                               a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[i + 4];
+                               c = (c << 30) | (c >> 2);
+                               i += 5;
+                       }
 
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[72];
-                       e = (e << 30) | (e >> 2);
+                       _H[0] += a;
+                       _H[1] += b;
+                       _H[2] += c;
+                       _H[3] += d;
+                       _H[4] += e;
+               }
 
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[73];
-                       d = (d << 30) | (d >> 2);
+               private static void InitialiseBuff(uint[] buff, byte[] input, uint inputOffset)
+               {
+                       buff[0] = (uint)((input[inputOffset + 0] << 24) | (input[inputOffset + 1] << 16) | (input[inputOffset + 2] << 8) | (input[inputOffset + 3]));
+                       buff[1] = (uint)((input[inputOffset + 4] << 24) | (input[inputOffset + 5] << 16) | (input[inputOffset + 6] << 8) | (input[inputOffset + 7]));
+                       buff[2] = (uint)((input[inputOffset + 8] << 24) | (input[inputOffset + 9] << 16) | (input[inputOffset + 10] << 8) | (input[inputOffset + 11]));
+                       buff[3] = (uint)((input[inputOffset + 12] << 24) | (input[inputOffset + 13] << 16) | (input[inputOffset + 14] << 8) | (input[inputOffset + 15]));
+                       buff[4] = (uint)((input[inputOffset + 16] << 24) | (input[inputOffset + 17] << 16) | (input[inputOffset + 18] << 8) | (input[inputOffset + 19]));
+                       buff[5] = (uint)((input[inputOffset + 20] << 24) | (input[inputOffset + 21] << 16) | (input[inputOffset + 22] << 8) | (input[inputOffset + 23]));
+                       buff[6] = (uint)((input[inputOffset + 24] << 24) | (input[inputOffset + 25] << 16) | (input[inputOffset + 26] << 8) | (input[inputOffset + 27]));
+                       buff[7] = (uint)((input[inputOffset + 28] << 24) | (input[inputOffset + 29] << 16) | (input[inputOffset + 30] << 8) | (input[inputOffset + 31]));
+                       buff[8] = (uint)((input[inputOffset + 32] << 24) | (input[inputOffset + 33] << 16) | (input[inputOffset + 34] << 8) | (input[inputOffset + 35]));
+                       buff[9] = (uint)((input[inputOffset + 36] << 24) | (input[inputOffset + 37] << 16) | (input[inputOffset + 38] << 8) | (input[inputOffset + 39]));
+                       buff[10] = (uint)((input[inputOffset + 40] << 24) | (input[inputOffset + 41] << 16) | (input[inputOffset + 42] << 8) | (input[inputOffset + 43]));
+                       buff[11] = (uint)((input[inputOffset + 44] << 24) | (input[inputOffset + 45] << 16) | (input[inputOffset + 46] << 8) | (input[inputOffset + 47]));
+                       buff[12] = (uint)((input[inputOffset + 48] << 24) | (input[inputOffset + 49] << 16) | (input[inputOffset + 50] << 8) | (input[inputOffset + 51]));
+                       buff[13] = (uint)((input[inputOffset + 52] << 24) | (input[inputOffset + 53] << 16) | (input[inputOffset + 54] << 8) | (input[inputOffset + 55]));
+                       buff[14] = (uint)((input[inputOffset + 56] << 24) | (input[inputOffset + 57] << 16) | (input[inputOffset + 58] << 8) | (input[inputOffset + 59]));
+                       buff[15] = (uint)((input[inputOffset + 60] << 24) | (input[inputOffset + 61] << 16) | (input[inputOffset + 62] << 8) | (input[inputOffset + 63]));
+               }
 
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[74];
-                       c = (c << 30) | (c >> 2);
+               private static void FillBuff(uint[] buff)
+               {
+                       uint val;
+                       for (int i = 16; i < 80; i += 8)
+                       {
+                               val = buff[i - 3] ^ buff[i - 8] ^ buff[i - 14] ^ buff[i - 16];
+                               buff[i] = (val << 1) | (val >> 31);
 
-                       e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[75];
-                       b = (b << 30) | (b >> 2);
+                               val = buff[i - 2] ^ buff[i - 7] ^ buff[i - 13] ^ buff[i - 15];
+                               buff[i + 1] = (val << 1) | (val >> 31);
 
-                       d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[76];
-                       a = (a << 30) | (a >> 2);
+                               val = buff[i - 1] ^ buff[i - 6] ^ buff[i - 12] ^ buff[i - 14];
+                               buff[i + 2] = (val << 1) | (val >> 31);
 
-                       c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[77];
-                       e = (e << 30) | (e >> 2);
+                               val = buff[i + 0] ^ buff[i - 5] ^ buff[i - 11] ^ buff[i - 13];
+                               buff[i + 3] = (val << 1) | (val >> 31);
 
-                       b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[78];
-                       d = (d << 30) | (d >> 2);
+                               val = buff[i + 1] ^ buff[i - 4] ^ buff[i - 10] ^ buff[i - 12];
+                               buff[i + 4] = (val << 1) | (val >> 31);
 
-                       a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[79];
-                       c = (c << 30) | (c >> 2);
+                               val = buff[i + 2] ^ buff[i - 3] ^ buff[i - 9] ^ buff[i - 11];
+                               buff[i + 5] = (val << 1) | (val >> 31);
 
+                               val = buff[i + 3] ^ buff[i - 2] ^ buff[i - 8] ^ buff[i - 10];
+                               buff[i + 6] = (val << 1) | (val >> 31);
 
-                       _H[0] += a;
-                       _H[1] += b;
-                       _H[2] += c;
-                       _H[3] += d;
-                       _H[4] += e;
+                               val = buff[i + 4] ^ buff[i - 1] ^ buff[i - 7] ^ buff[i - 9];
+                               buff[i + 7] = (val << 1) | (val >> 31);
+                       }
                }
        
                private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
index 52fada0ee32d4f5204848c55ee99de333e58f407..17c72c4734229ca332d66caf66d5e18544bef93f 100644 (file)
@@ -39,7 +39,6 @@ namespace System.Security.Cryptography {
                private const int BLOCK_SIZE_BYTES =  64;
                private const int HASH_SIZE_BYTES  =  32;
                private uint[] _H;
-               private uint[] K;
                private ulong count;
                private byte[] _ProcessingBuffer;   // Used to start data when passed less than a block worth.
                private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
@@ -53,44 +52,6 @@ namespace System.Security.Cryptography {
                        Initialize ();
                }
 
-               private uint Ch (uint u, uint v, uint w) 
-               {
-                       return (u&v) ^ (~u&w);
-               }
-
-               private uint Maj (uint u, uint v, uint w) 
-               {
-                       return (u&v) ^ (u&w) ^ (v&w);
-               }
-
-               private uint Ro0 (uint x) 
-               {
-                       return ((x >> 7) | (x << 25))
-                               ^ ((x >> 18) | (x << 14))
-                               ^ (x >> 3);
-               }
-
-               private uint Ro1 (uint x) 
-               {
-                       return ((x >> 17) | (x << 15))
-                               ^ ((x >> 19) | (x << 13))
-                               ^ (x >> 10);
-               }
-
-               private uint Sig0 (uint x) 
-               {
-                       return ((x >> 2) | (x << 30))
-                               ^ ((x >> 13) | (x << 19))
-                               ^ ((x >> 22) | (x << 10));
-               }
-
-               private uint Sig1 (uint x) 
-               {
-                       return ((x >> 6) | (x << 26))
-                               ^ ((x >> 11) | (x << 21))
-                               ^ ((x >> 25) | (x << 7));
-               }
-
                protected override void HashCore (byte[] rgb, int start, int size) 
                {
                        int i;
@@ -159,19 +120,26 @@ namespace System.Security.Cryptography {
                        uint a, b, c, d, e, f, g, h;
                        uint t1, t2;
                        int i;
+                       uint[] K1 = SHAConstants.K1;
+                       uint[] buff = this.buff;
                
                        count += BLOCK_SIZE_BYTES;
 
                        for (i=0; i<16; i++) {
-                               buff[i] = ((uint)(inputBuffer[inputOffset+4*i]) << 24)
-                                       | ((uint)(inputBuffer[inputOffset+4*i+1]) << 16)
-                                       | ((uint)(inputBuffer[inputOffset+4*i+2]) <<  8)
-                                       | ((uint)(inputBuffer[inputOffset+4*i+3]));
+                               buff[i] = (uint)(((inputBuffer[inputOffset + 4 * i]) << 24)
+                                       | ((inputBuffer[inputOffset + 4 * i + 1]) << 16)
+                                       | ((inputBuffer[inputOffset + 4 * i + 2]) << 8)
+                                       | ((inputBuffer[inputOffset + 4 * i + 3])));
                        }
 
                
                        for (i=16; i<64; i++) {
-                               buff[i] = Ro1(buff[i-2]) + buff[i-7] + Ro0(buff[i-15]) + buff[i-16];
+                               t1 = buff[i - 15];
+                               t1 = (((t1 >> 7) | (t1 << 25)) ^ ((t1 >> 18) | (t1 << 14)) ^ (t1 >> 3));
+
+                               t2 = buff[i - 2];
+                               t2 = (((t2 >> 17) | (t2 << 15)) ^ ((t2 >> 19) | (t2 << 13)) ^ (t2 >> 10));
+                               buff[i] = t2 + buff[i - 7] + t1 + buff[i - 16];
                        }
 
                        a = _H[0];
@@ -184,8 +152,10 @@ namespace System.Security.Cryptography {
                        h = _H[7];
 
                        for (i=0; i<64; i++) {
-                               t1 = h + Sig1(e) + Ch(e,f,g) + SHAConstants.K1 [i] + buff[i];
-                               t2 = Sig0(a) + Maj(a,b,c);
+                               t1 = h + (((e >> 6) | (e << 26)) ^ ((e >> 11) | (e << 21)) ^ ((e >> 25) | (e << 7))) + ((e & f) ^ (~e & g)) + K1[i] + buff[i];
+
+                               t2 = (((a >> 2) | (a << 30)) ^ ((a >> 13) | (a << 19)) ^ ((a >> 22) | (a << 10)));
+                               t2 = t2 + ((a & b) ^ (a & c) ^ (b & c));
                                h = g;
                                g = f;
                                f = e;
index 45eb1551e1dca3beee99d1af2da9eec016194fc9..9238fe15672c7c1772daf0095a670f7652658d6d 100644 (file)
@@ -199,24 +199,40 @@ public class SHA384Managed : SHA384 {
 
        private void processBlock ()
        {
+               ulong a, b, c, d, e, f, g, h;
+
+               // abcrem doesn't work on fields
+               ulong[] W = this.W;
+               ulong[] K2 = SHAConstants.K2;
+
                adjustByteCounts ();
                // expand 16 word block into 80 word blocks.
                for (int t = 16; t <= 79; t++)
-                       W[t] = Sigma1 (W [t - 2]) + W [t - 7] + Sigma0 (W [t - 15]) + W [t - 16];
-
+               {
+                       a = W[t-15];
+                       a = ((a >> 1) | (a << 63)) ^ ((a >> 8) | (a << 56)) ^ (a >> 7);
+                       b = W[t - 2];
+                       b = ((b >> 19) | (b << 45)) ^ ((b >> 61) | (b << 3)) ^ (b >> 6);
+                       W[t] = b + W[t - 7] + a + W[t - 16];
+               }
                // set up working variables.
-               ulong a = H1;
-               ulong b = H2;
-               ulong c = H3;
-               ulong d = H4;
-               ulong e = H5;
-               ulong f = H6;
-               ulong g = H7;
-               ulong h = H8;
-
-               for (int t = 0; t <= 79; t++) {
-                       ulong T1 = h + Sum1 (e) + Ch (e, f, g) + SHAConstants.K2 [t] + W [t];
-                       ulong T2 = Sum0 (a) + Maj (a, b, c);
+               a = H1;
+               b = H2;
+               c = H3;
+               d = H4;
+               e = H5;
+               f = H6;
+               g = H7;
+               h = H8;
+
+               for (int t = 0; t <= 79; t++)
+               {
+                       ulong T1 = ((e >> 14) | (e << 50)) ^ ((e >> 18) | (e << 46)) ^ ((e >> 41) | (e << 23));
+                       T1 += h + ((e & f) ^ ((~e) & g)) + SHAConstants.K2[t] + W[t];
+
+                       ulong T2 = ((a >> 28) | (a << 36)) ^ ((a >> 34) | (a << 30)) ^ ((a >> 39) | (a << 25));
+                       T2 += ((a & b) ^ (a & c) ^ (b & c));
+
                        h = g;
                        g = f;
                        f = e;
@@ -240,42 +256,6 @@ public class SHA384Managed : SHA384 {
                for (int i = 0; i != W.Length; i++)
                        W[i] = 0;
        }
-
-       private ulong rotateRight (ulong x, int n)
-       {
-               return (x >> n) | (x << (64 - n));
-       }
-
-       /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
-       private ulong Ch (ulong x, ulong y, ulong z)
-       {
-               return ((x & y) ^ ((~x) & z));
-       }
-
-       private ulong Maj (ulong x, ulong y, ulong z)
-       {
-               return ((x & y) ^ (x & z) ^ (y & z));
-       }
-
-       private ulong Sum0 (ulong x)
-       {
-               return rotateRight (x, 28) ^ rotateRight (x, 34) ^ rotateRight (x, 39);
-       }
-
-       private ulong Sum1 (ulong x)
-       {
-               return rotateRight (x, 14) ^ rotateRight (x, 18) ^ rotateRight (x, 41);
-       }
-
-       private ulong Sigma0 (ulong x)
-       {
-               return rotateRight (x, 1) ^ rotateRight(x, 8) ^ (x >> 7);
-       }
-
-       private ulong Sigma1 (ulong x)
-       {
-               return rotateRight (x, 19) ^ rotateRight (x, 61) ^ (x >> 6);
-       }
 }
 
 }
index 0507a91709123e1645cbccfcf36659dc36a92e63..3e51c2ac16f1ef9d66578ea20502eeb17983a5f1 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * DictionaryTest.cs: Added not working tests for bug #384723. Spaces
+       to tabs.
+
 2008-03-21  Sebastien Pouliot  <sebastien@ximian.com>
 
        * EqualityComparerTest.cs: New. Add test cases for using null with 
index 8289c3a8351fbcd357b839036989aee09275c5e4..425a0d14a14a920a01701765b4205a83c1e148e1 100644 (file)
@@ -37,6 +37,8 @@ using System.Collections.Generic;
 using System.IO;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Text;
+using System.Threading;
+
 using NUnit.Framework;
 
 namespace MonoTests.System.Collections.Generic {
@@ -208,6 +210,29 @@ namespace MonoTests.System.Collections.Generic {
                        Assert.AreEqual (20, _dictionary2 [m2].Value, "#4");
                        
                }
+
+               [Test]
+               [Category ("NotWorking")]
+               public void Remove_ZeroOut ()
+               {
+                       object key = new object ();
+                       object value = new object ();
+
+                       WeakReference wrKey = new WeakReference (key);
+                       WeakReference wrValue = new WeakReference (value);
+
+                       Dictionary <object, object> dictionary = new Dictionary <object, object> ();
+                       dictionary.Add (key, value);
+                       dictionary.Remove (key);
+
+                       key = null;
+                       value = null;
+                       GC.Collect ();
+                       Thread.Sleep (200);
+
+                       Assert.IsNull (wrKey.Target, "#1");
+                       Assert.IsNull (wrValue.Target, "#2");
+               }
        
                [Test, ExpectedException(typeof(ArgumentNullException))]
                public void IndexerSetNullTest()
@@ -226,7 +251,30 @@ namespace MonoTests.System.Collections.Generic {
                        Assert.AreEqual (0, _dictionary.Count, "Clear method failed!");
                        Assert.IsFalse (_dictionary.ContainsKey ("key2"));
                }
-       
+
+               [Test]
+               [Category ("NotWorking")]
+               public void Clear_ZeroOut ()
+               {
+                       object key = new object ();
+                       object value = new object ();
+
+                       WeakReference wrKey = new WeakReference (key);
+                       WeakReference wrValue = new WeakReference (value);
+
+                       Dictionary <object, object> dictionary = new Dictionary <object, object> ();
+                       dictionary.Add (key, value);
+                       dictionary.Clear ();
+
+                       key = null;
+                       value = null;
+                       GC.Collect ();
+                       Thread.Sleep (200);
+
+                       Assert.IsNull (wrKey.Target, "#1");
+                       Assert.IsNull (wrValue.Target, "#2");
+               }
+
                [Test]
                public void ContainsKeyTest ()
                {
@@ -302,7 +350,6 @@ namespace MonoTests.System.Collections.Generic {
                                return myt.Name.Equals (this.Name) &&
                                                myt.RollNo.Equals (this.RollNo);
                        }
-       
                }
        
                [Test]
@@ -362,7 +409,6 @@ namespace MonoTests.System.Collections.Generic {
                                KeyValuePair <string, object> entry = (KeyValuePair <string, object>)itr.Current;
                        }
                        Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
-       
                }
        
                [Test]
@@ -379,7 +425,6 @@ namespace MonoTests.System.Collections.Generic {
                                DictionaryEntry entry = (DictionaryEntry) itr.Current;
                        }
                        Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
-       
                }
        
                [Test]
@@ -445,37 +490,37 @@ namespace MonoTests.System.Collections.Generic {
                [Test]
                public void KeyValueEnumeratorTest ()
                {
-                       IDictionary<int, int> d = new Dictionary<int, int>();
+                       IDictionary<int, int> d = new Dictionary<int, int>();
 
                        // Values are chosen such that two keys map to the same bucket.
                        // Default dictionary table size == 10
-                       d [9] = 1;
-                       d [10] = 2;
-                       d [19] = 3;
+                       d [9] = 1;
+                       d [10] = 2;
+                       d [19] = 3;
 
                        Assert.AreEqual (d.Count, d.Keys.Count, "d and d.Keys don't appear to match");
                        Assert.AreEqual (d.Values.Count, d.Keys.Count, "d.Keys and d.Values don't appear to match");
 
-                       int count = 0;
-                       foreach (int i in d.Values)
-                               ++count;
+                       int count = 0;
+                       foreach (int i in d.Values)
+                               ++count;
                        Assert.AreEqual (count, d.Values.Count, "d.Values doesn't have the correct number of elements");
        
-                       count = 0;
+                       count = 0;
                        foreach (int i in d.Keys)
                                ++count;
                        Assert.AreEqual (count, d.Keys.Count, "d.Keys doesn't have the correct number of elements");
 
                        int nkeys = count;
                        count = 0;
-                       foreach (int i in d.Keys) {
+                       foreach (int i in d.Keys) {
                                int foo = d [i];
                                if (count++ >= nkeys)
                                        Assert.Fail ("Reading a value appears to trash enumerator state");
                        }
                }
 
-               [Test]          // bug 75073
+               [Test] // bug 75073
                public void SliceCollectionsEnumeratorTest ()
                {
                        Dictionary<string, int> values = new Dictionary<string, int> ();
@@ -692,8 +737,7 @@ namespace MonoTests.System.Collections.Generic {
                        Assert.IsNull(d["foo"]);
                }
 
-               // Bug: #332534
-               [Test]
+               [Test] // bug #332534
                public void Dictionary_MoveNext ()
                {
                        Dictionary<int,int> a = new Dictionary<int,int>();
index 70fba70d05341c5ccf3985d78585e78e8608a85b..7056f189568705aa2b31bc699799f30060d33eba 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * DirectoryTest.cs: Do not use ExpectedException to avoid false
+       positives. Use String.Empty instead of "".
+
 2008-04-22  Dick Porter  <dick@ximian.com>
 
        * FileTest.cs: Disable the test for bug 323389, as I've reverted
index fe212c342a0d281c700e285bea308a12cb1a461a..915bb93dd72985b5f2d34357a93d24b8e6e16ecd 100644 (file)
@@ -37,7 +37,8 @@ public class DirectoryTest
        }\r
        \r
        [TearDown]\r
-       public void TearDown () {\r
+       public void TearDown ()\r
+       {\r
                if (Directory.Exists (TempFolder))\r
                        Directory.Delete (TempFolder, true);\r
        }\r
@@ -64,36 +65,63 @@ public class DirectoryTest
                DeleteDirectory (":");\r
                try {\r
                        DirectoryInfo info = Directory.CreateDirectory (":");\r
-                       Assert.Fail ();\r
-               } catch (ArgumentException) {\r
+                       Assert.Fail ("#1");\r
+               } catch (ArgumentException ex) {\r
+                       // The path is not of a legal form\r
+                       Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");\r
+                       Assert.IsNull (ex.InnerException, "#3");\r
+                       Assert.IsNotNull (ex.Message, "#4");\r
+                       Assert.IsNull (ex.ParamName, "#5");\r
                }\r
                DeleteDirectory (":");\r
        }\r
 \r
        [Test]\r
-       [ExpectedException(typeof(ArgumentNullException))]\r
-       public void CreateDirectoryArgumentNullException ()\r
+       public void CreateDirectory_Path_Null ()\r
        {\r
-               DirectoryInfo info = Directory.CreateDirectory (null as string);\r
+               try {\r
+                       Directory.CreateDirectory (null as string);\r
+                       Assert.Fail ("#1");\r
+               } catch (ArgumentNullException ex) {\r
+                       Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");\r
+                       Assert.IsNull (ex.InnerException, "#3");\r
+                       Assert.IsNotNull (ex.Message, "#4");\r
+                       Assert.AreEqual ("path", ex.ParamName, "#5");\r
+               }\r
        }\r
 \r
        [Test]\r
-       [ExpectedException(typeof(ArgumentException))]\r
-       public void CreateDirectoryArgumentException1 ()\r
+       public void CreateDirectory_Path_Empty ()\r
        {\r
-               DirectoryInfo info = Directory.CreateDirectory ("");\r
+               try {\r
+                       Directory.CreateDirectory (string.Empty);\r
+                       Assert.Fail ("#1");\r
+               } catch (ArgumentException ex) {\r
+                       // Path cannot be the empty string or all whitespace\r
+                       Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");\r
+                       Assert.IsNull (ex.InnerException, "#3");\r
+                       Assert.IsNotNull (ex.Message, "#4");\r
+                       Assert.IsNull (ex.ParamName, "#5");\r
+               }\r
        }\r
 \r
        [Test]\r
-       [ExpectedException(typeof(ArgumentException))]\r
-       public void CreateDirectoryArgumentException2 ()\r
+       public void CreateDirectory_Path_Whitespace ()\r
        {\r
-               DirectoryInfo info = Directory.CreateDirectory ("            ");\r
+               try {\r
+                       Directory.CreateDirectory ("            ");\r
+                       Assert.Fail ("#1");\r
+               } catch (ArgumentException ex) {\r
+                       // The path is not of a legal form\r
+                       Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");\r
+                       Assert.IsNull (ex.InnerException, "#3");\r
+                       Assert.IsNotNull (ex.Message, "#4");\r
+                       Assert.IsNull (ex.ParamName, "#5");\r
+               }\r
        }\r
 \r
        [Test]\r
-       [ExpectedException(typeof(ArgumentException))]\r
-       public void CreateDirectoryArgumentException3 ()\r
+       public void CreateDirectory_Path_InvalidChars ()\r
        {\r
                string path = TempFolder + DSC + "DirectoryTest.Test";\r
                DeleteDirectory (path);\r
@@ -101,6 +129,13 @@ public class DirectoryTest
                        path += '\x00';\r
                        path += ".2";\r
                        DirectoryInfo info = Directory.CreateDirectory (path);\r
+                       Assert.Fail ("#1");\r
+               } catch (ArgumentException ex) {\r
+                       // The path contains illegal characters\r
+                       Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");\r
+                       Assert.IsNull (ex.InnerException, "#3");\r
+                       Assert.IsNotNull (ex.Message, "#4");\r
+                       Assert.IsNull (ex.ParamName, "#5");\r
                } finally {\r
                        DeleteDirectory (path);\r
                }\r
@@ -189,7 +224,7 @@ public class DirectoryTest
        [ExpectedException(typeof(ArgumentException))]\r
        public void DeleteArgumentException ()\r
        {\r
-               Directory.Delete ("");\r
+               Directory.Delete (string.Empty);\r
        }\r
 \r
        [Test]  \r
@@ -309,7 +344,7 @@ public class DirectoryTest
        [Category("TargetJvmNotSupported")] // GetCreationTime not supported for TARGET_JVM\r
        public void GetCreationTimeException2 ()\r
        {\r
-               Directory.GetCreationTime ("");\r
+               Directory.GetCreationTime (string.Empty);\r
        }\r
        \r
        [Test]\r
@@ -367,7 +402,7 @@ public class DirectoryTest
        [Category("TargetJvmNotSupported")] // GetCreationTime not supported for TARGET_JVM\r
        public void GetCreationTimeUtcException2 ()\r
        {\r
-               Directory.GetCreationTimeUtc ("");\r
+               Directory.GetCreationTimeUtc (string.Empty);\r
        }\r
        \r
        [Test]\r
@@ -425,7 +460,7 @@ public class DirectoryTest
        [Category("TargetJvmNotSupported")] // GetLastAccessTime not supported for TARGET_JVM\r
        public void GetLastAccessTimeException2 ()\r
        {\r
-               Directory.GetLastAccessTime ("");\r
+               Directory.GetLastAccessTime (string.Empty);\r
        }\r
        \r
        [Test]\r
@@ -484,7 +519,7 @@ public class DirectoryTest
        [Category("TargetJvmNotSupported")] // GetLastAccessTime not supported for TARGET_JVM\r
        public void GetLastAccessTimeUtcException2 ()\r
        {\r
-               Directory.GetLastAccessTimeUtc ("");\r
+               Directory.GetLastAccessTimeUtc (string.Empty);\r
        }\r
        \r
        [Test]\r
@@ -539,7 +574,7 @@ public class DirectoryTest
        [ExpectedException(typeof(ArgumentException))]\r
        public void GetLastWriteTimeException2 ()\r
        {\r
-               Directory.GetLastWriteTime ("");\r
+               Directory.GetLastWriteTime (string.Empty);\r
        }\r
        \r
        [Test]\r
@@ -592,7 +627,7 @@ public class DirectoryTest
        [ExpectedException(typeof(ArgumentException))]\r
        public void GetLastWriteTimeUtcException2 ()\r
        {\r
-               Directory.GetLastWriteTimeUtc ("");\r
+               Directory.GetLastWriteTimeUtc (string.Empty);\r
        }\r
        \r
        [Test]\r
@@ -1072,7 +1107,7 @@ public class DirectoryTest
        public void SetLastWriteTimeException2 ()\r
        {\r
                DateTime time = new DateTime (2003, 4, 6, 6, 4, 2);\r
-               Directory.SetLastWriteTime ("", time);\r
+               Directory.SetLastWriteTime (string.Empty, time);\r
        }\r
        \r
        [Test]\r
@@ -1136,7 +1171,7 @@ public class DirectoryTest
        public void SetLastWriteTimeUtcException2 ()\r
        {\r
                DateTime time = new DateTime (2003, 4, 6, 6, 4, 2);\r
-               Directory.SetLastWriteTimeUtc ("", time);\r
+               Directory.SetLastWriteTimeUtc (string.Empty, time);\r
        }\r
        \r
        [Test]\r
@@ -1200,7 +1235,7 @@ public class DirectoryTest
        public void SetLastAccessTimeException2 ()\r
        {\r
                DateTime time = new DateTime (2003, 4, 6, 6, 4, 2);\r
-               Directory.SetLastAccessTime ("", time);\r
+               Directory.SetLastAccessTime (string.Empty, time);\r
        }\r
        \r
        [Test]\r
@@ -1268,7 +1303,7 @@ public class DirectoryTest
        public void SetLastAccessTimeUtcException2 ()\r
        {\r
                DateTime time = new DateTime (2003, 4, 6, 6, 4, 2);\r
-               Directory.SetLastAccessTimeUtc ("", time);\r
+               Directory.SetLastAccessTimeUtc (string.Empty, time);\r
        }\r
        \r
        [Test]\r
@@ -1335,7 +1370,7 @@ public class DirectoryTest
        public void SetCreationTimeException2 ()\r
        {\r
                DateTime time = new DateTime (2003, 4, 6, 6, 4, 2);\r
-               Directory.SetCreationTime ("", time);\r
+               Directory.SetCreationTime (string.Empty, time);\r
        }\r
        \r
        [Test]\r
@@ -1405,7 +1440,7 @@ public class DirectoryTest
        public void SetCreationTimeUtcException2 ()\r
        {\r
                DateTime time = new DateTime (2003, 4, 6, 6, 4, 2);\r
-               Directory.SetCreationTimeUtc ("", time);\r
+               Directory.SetCreationTimeUtc (string.Empty, time);\r
        }\r
        \r
        [Test]\r
index 5f8ad31d47e2963382c8259bc1051afc57cda5be..e2e3de77f6b7e6088206cdb18a3b30f2eb994d8f 100644 (file)
@@ -1,3 +1,23 @@
+2008-05-01  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * ConstructorBuilderTest.cs: Use Assert class instead of deriving from
+       deprecated Assertion class. Improved some existing tests, and avoid
+       creating too much TypeBuilder instances.
+
+2008-04-30  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * MethodOnTypeBuilderInstTest.cs: Fixed exception message in comments.
+       * TypeBuilderTest.cs: Do not use ExpectedException to avoid false
+       positives. Added argument check tests for DefineEvent, DefineField,
+       DefineMethod, DefinePInvokeMethod and DefinePropety. Use
+       Type.EmptyTypes instead of constructing empty array.
+       * ConstructorBuilderTest.cs: Added Test attributes. Added tests
+       for DefineParameter and Invoke overloads. Added tests for
+       GetCustomAttributes overloads. Avoid use of ExpectedException.
+       * ModuleBuilderTest.cs: Added tests for DefineType name argument
+       checks.
+       * ConstructorOnTypeBuilderInstTest.cs: Added basic set of tests.
+
 2008-04-26  Gert Driesen  <drieseng@users.sourceforge.net>
 
        * MethodOnTypeBuilderInstTest.cs: Added basic set of tests.
index 2d380965e0b25ef4aa8c2a354a5470c74d1323af..2a9426c7f48ed4d57cb713a30592e51009fcaa8d 100644 (file)
@@ -20,18 +20,17 @@ using NUnit.Framework;
 
 namespace MonoTests.System.Reflection.Emit
 {
-
 [TestFixture]
-public class ConstructorBuilderTest : Assertion
-{      
-    private TypeBuilder genClass;
-
+public class ConstructorBuilderTest
+{
+       private TypeBuilder genClass;
        private ModuleBuilder module;
 
        private static int typeIndexer = 0;
 
        [SetUp]
-       protected void SetUp () {
+       public void SetUp ()
+       {
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = "MonoTests.System.Reflection.Emit.ConstructorBuilderTest";
 
@@ -40,156 +39,282 @@ public class ConstructorBuilderTest : Assertion
                                assemblyName, AssemblyBuilderAccess.Run);
 
                module = assembly.DefineDynamicModule("module1");
-               
-               genClass = module.DefineType(genTypeName (), 
-                                                                        TypeAttributes.Public);
+               genClass = module.DefineType(genTypeName (), TypeAttributes.Public);
        }
 
        // Return a unique type name
-       private string genTypeName () {
+       private string genTypeName ()
+       {
                return "class" + (typeIndexer ++);
        }
 
-       public void TestAttributes () {
+       [Test]
+       public void Attributes ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        MethodAttributes.Public, 0, new Type [0]);
+                       MethodAttributes.Public, 0, new Type [0]);
 
-               Assert ("Attributes works", 
-                               (cb.Attributes & MethodAttributes.Public) != 0);
-               Assert ("Attributes works", 
-                               (cb.Attributes & MethodAttributes.SpecialName) != 0);
+               Assert.IsTrue ((cb.Attributes & MethodAttributes.Public) != 0, "#1");
+               Assert.IsTrue ((cb.Attributes & MethodAttributes.SpecialName) != 0, "#2");
        }
 
-       public void TestCallingConvention () {
+       [Test]
+       public void CallingConvention ()
+       {
                /* This does not work under MS.NET
                ConstructorBuilder cb3 = genClass.DefineConstructor (
                        0, CallingConventions.VarArgs, new Type [0]);
-               AssertEquals ("CallingConvetion works",
-                                         CallingConventions.VarArgs | CallingConventions.HasThis,
-                                         cb3.CallingConvention);
+               Assert.AreEqual (CallingConventions.VarArgs | CallingConventions.HasThis,
+                       cb3.CallingConvention, "#1");
                */
 
                ConstructorBuilder cb4 = genClass.DefineConstructor (
                         MethodAttributes.Static, CallingConventions.Standard, new Type [0]);
-               AssertEquals ("Static implies !HasThis",
-                                         cb4.CallingConvention,
-                                         CallingConventions.Standard);
+               Assert.AreEqual (CallingConventions.Standard,
+                       cb4.CallingConvention, "#2");
        }
 
-       public void TestDeclaringType () {
+       [Test]
+       public void DeclaringType ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        0, 0, new Type[0]);
+                       0, 0, new Type[0]);
 
-               AssertEquals ("DeclaringType works",
-                                         cb.DeclaringType, genClass);
+               Assert.AreSame (genClass, cb.DeclaringType);
        }
 
-       public void TestInitLocals () {
+       [Test]
+       public void InitLocals ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        0, 0, new Type[0]);
+                       0, 0, new Type[0]);
 
-               AssertEquals ("InitLocals defaults to true", cb.InitLocals, true);
+               Assert.IsTrue (cb.InitLocals, "#1");
                cb.InitLocals = false;
-               AssertEquals ("InitLocals is settable", cb.InitLocals, false);
+               Assert.IsFalse (cb.InitLocals, "#2");
        }
        
        [Test]
-       [Category ("NotDotNet")]
-       public void TestMethodHandle ()
+       public void MethodHandle ()
        {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        0, 0, new Type [0]);
+                       0, 0, new Type [0]);
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
 
-               RuntimeMethodHandle handle = cb.MethodHandle;
-               // the previous line throws a NotSupportedException on MS 1.1 SP1
-       }
+               try {
+                       RuntimeMethodHandle handle = cb.MethodHandle;
+                       Assert.Fail ("#A1:" + handle);
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+               }
 
-       public void TestName () {
-               ConstructorBuilder cb = genClass.DefineConstructor (0, 0, new Type [0]);
+               genClass.CreateType ();
 
-               AssertEquals ("Name works", ".ctor", cb.Name);
+               try {
+                       RuntimeMethodHandle handle = cb.MethodHandle;
+                       Assert.Fail ("#B1:" + handle);
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
+               }
+       }
 
-               ConstructorBuilder cb2 = genClass.DefineConstructor (MethodAttributes.Static, 0, new Type [0]);
-               AssertEquals ("Static constructors have the right name", ".cctor", cb2.Name);
+       [Test]
+       public void Name ()
+       {
+               ConstructorBuilder cb;
+               
+               cb = genClass.DefineConstructor (0, 0, new Type [0]);
+               Assert.AreEqual (".ctor", cb.Name, "#1");
+               cb = genClass.DefineConstructor (MethodAttributes.Static, 0, new Type [0]);
+               Assert.AreEqual (".cctor", cb.Name, "#2");
        }
 
-       public void TestReflectedType () {
+       [Test]
+       public void TestReflectedType ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (0, 0, new Type [0]);
 
-               AssertEquals ("ReflectedType works", 
-                                         genClass, cb.ReflectedType);
+               Assert.AreSame (genClass, cb.ReflectedType);
        }
 
-       public void TestReturnType () {
-               ConstructorBuilder cb = genClass.DefineConstructor (0, 0, new Type [0]);
-
-               AssertEquals ("ReturnType works", 
-                                         null, cb.ReturnType);
+       [Test]
+       public void ReturnType ()
+       {
+               ConstructorBuilder cb;
+               
+               cb = genClass.DefineConstructor (0, 0, new Type [] { typeof (string) });
+               Assert.IsNull (cb.ReturnType, "#1");
+               cb = genClass.DefineConstructor (MethodAttributes.Static, 0, new Type [0]);
+               Assert.IsNull (cb.ReturnType, "#2");
        }
 
-       public void TestDefineParameter () {
-               TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
-               ConstructorBuilder cb = tb.DefineConstructor (
-                        0, 0, new Type [2] { typeof(int), typeof(int) });
+       [Test]
+       public void DefineParameter_Position_Negative ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       0, 0, new Type [2] { typeof (int), typeof (int) });
 
-               // index out of range
                try {
-                       cb.DefineParameter (0, 0, "param1");
-                       Fail ();
-               } catch (ArgumentOutOfRangeException) {
+                       cb.DefineParameter (-1, ParameterAttributes.None, "param1");
+                       Assert.Fail ("#1");
+               } catch (ArgumentOutOfRangeException ex) {
+                       // Specified argument was out of the range of valid values
+                       Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.ActualValue, "#3");
+                       Assert.IsNull (ex.InnerException, "#4");
+                       Assert.IsNotNull (ex.Message, "#5");
+                       Assert.IsNotNull (ex.ParamName, "#6");
                }
+       }
+
+       [Test]
+       public void DefineParameter_Position_Max ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        0, 0, new Type [2] { typeof (int), typeof (int) });
+
                try {
                        cb.DefineParameter (3, 0, "param1");
-                       Fail ();
-               } catch (ArgumentOutOfRangeException) {
+                       Assert.Fail ("#1");
+               } catch (ArgumentOutOfRangeException ex) {
+                       // Specified argument was out of the range of valid values
+                       Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.ActualValue, "#3");
+                       Assert.IsNull (ex.InnerException, "#4");
+                       Assert.IsNotNull (ex.Message, "#5");
+                       Assert.IsNotNull (ex.ParamName, "#6");
+               }
+       }
+
+       [Test]
+#if NET_2_0
+       [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=341439
+#endif
+       public void DefineParameter_Position_Zero ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       0, 0, new Type [2] { typeof (int), typeof (int) });
+
+               try {
+                       cb.DefineParameter (0, ParameterAttributes.In, "param1");
+                       Assert.Fail ("#1");
+               } catch (ArgumentOutOfRangeException ex) {
+                       // Specified argument was out of the range of valid values
+                       Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.ActualValue, "#3");
+                       Assert.IsNull (ex.InnerException, "#4");
+                       Assert.IsNotNull (ex.Message, "#5");
+                       Assert.IsNotNull (ex.ParamName, "#6");
                }
+       }
+
+       [Test]
+       public void DefineParameter ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        0, 0, new Type [2] { typeof(int), typeof(int) });
 
-               // Normal usage
                cb.DefineParameter (1, 0, "param1");
                cb.DefineParameter (1, 0, "param1");
                cb.DefineParameter (2, 0, null);
 
-               // Can not be called on a created type
                cb.GetILGenerator ().Emit (OpCodes.Ret);
-               tb.CreateType ();
+               genClass.CreateType ();
+
                try {
                        cb.DefineParameter (1, 0, "param1");
-                       Fail ();
-               }
-               catch (InvalidOperationException) {
+                       Assert.Fail ("#1");
+               } catch (InvalidOperationException ex) {
+                       // Unable to change after type has been created
+                       Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
                }
        }
 
-       public void TestGetCustomAttributes () {
+       [Test] // GetCustomAttributes (Boolean)
+       public void GetCustomAttributes1 ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
                        0, 0, new Type [1] {typeof(int)});
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
 
                try {
                        cb.GetCustomAttributes (true);
-                       Fail ();
-               } catch (NotSupportedException) {
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
                }
 
+               genClass.CreateType ();
+
                try {
-                       cb.GetCustomAttributes (null, true);
-                       Fail ();
-               } catch (NotSupportedException) {
+                       cb.GetCustomAttributes (true);
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
                }
        }
 
-       public void TestMethodImplementationFlags () {
+       [Test] // GetCustomAttributes (Type, Boolean)
+       public void GetCustomAttributes2 ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        0, 0, new Type [0]);
+                       0, 0, new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
 
-               AssertEquals ("MethodImplementationFlags defaults to Managed+IL",
-                                         cb.GetMethodImplementationFlags (),
-                                         MethodImplAttributes.Managed | MethodImplAttributes.IL);
+               try {
+                       cb.GetCustomAttributes (null, true);
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+               }
 
-               cb.SetImplementationFlags (MethodImplAttributes.OPTIL);
+               genClass.CreateType ();
 
-               AssertEquals ("SetImplementationFlags works",
-                                         cb.GetMethodImplementationFlags (),
-                                         MethodImplAttributes.OPTIL);
+               try {
+                       cb.GetCustomAttributes (null, true);
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
+               }
+       }
+
+       [Test]
+       public void TestMethodImplementationFlags ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       0, 0, new Type [0]);
+
+               Assert.AreEqual (MethodImplAttributes.Managed | MethodImplAttributes.IL,
+                       cb.GetMethodImplementationFlags (), "#A1");
+               cb.SetImplementationFlags (MethodImplAttributes.OPTIL);
+               Assert.AreEqual (MethodImplAttributes.OPTIL,
+                       cb.GetMethodImplementationFlags (), "#A2");
 
                // Can not be called on a created type
                TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
@@ -201,92 +326,306 @@ public class ConstructorBuilderTest : Assertion
                tb.CreateType ();
                try {
                        cb2.SetImplementationFlags (MethodImplAttributes.OPTIL);
-                       Fail ();
-               }
-               catch (InvalidOperationException) {
+                       Assert.Fail ("#B1");
+               } catch (InvalidOperationException ex) {
+                       // Unable to change after type has been created
+                       Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
                }
        }
 
-       public void TestGetModule () {
+       [Test]
+       public void GetModule ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        0, 0, new Type [0]);
+                       0, 0, new Type [0]);
 
-               AssertEquals ("GetModule works",
-                                         module, cb.GetModule ());
+               Assert.AreSame (module, cb.GetModule ());
        }
 
-       public void TestGetParameters () {
-               TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
-               ConstructorBuilder cb = tb.DefineConstructor (
-                        0, 0, new Type [1] {typeof(int)});
+       [Test]
+       public void GetParameters_Complete1 ()
+       {
+               ConstructorBuilder cb;
+               ParameterInfo [] parameters;
+
+               cb = genClass.DefineConstructor (MethodAttributes.Public,
+                       CallingConventions.Standard,
+                       new Type [] { typeof (int), typeof (string), typeof (bool) });
+               cb.DefineParameter (3, ParameterAttributes.In, "param3a");
+               cb.DefineParameter (3, ParameterAttributes.In, "param3b");
+               cb.DefineParameter (2, ParameterAttributes.Out, "param2");
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+               genClass.CreateType ();
+
+               parameters = cb.GetParameters ();
+               Assert.IsNotNull (parameters, "#A1");
+               Assert.AreEqual (3, parameters.Length, "#A2");
+
+               Assert.AreEqual (ParameterAttributes.None, parameters [0].Attributes, "#B1");
+               Assert.IsNull (parameters [0].Name, "#B2");
+               Assert.AreEqual (typeof (int), parameters [0].ParameterType, "#B3");
+               Assert.AreEqual (0, parameters [0].Position, "#B4");
+
+               Assert.AreEqual (ParameterAttributes.Out, parameters [1].Attributes, "#C1");
+               Assert.AreEqual ("param2", parameters [1].Name, "#C2");
+               Assert.AreEqual (typeof (string), parameters [1].ParameterType, "#C3");
+               Assert.AreEqual (1, parameters [1].Position, "#C4");
+
+               Assert.AreEqual (ParameterAttributes.In, parameters [2].Attributes, "#D1");
+               Assert.AreEqual ("param3b", parameters [2].Name, "#D2");
+               Assert.AreEqual (typeof (bool), parameters [2].ParameterType, "#D3");
+               Assert.AreEqual (2, parameters [2].Position, "#D4");
+       }
+
+       [Test]
+#if ONLY_1_1
+       [Category ("NotDotNet")] // ArgumentNullException in GetParameters
+#endif
+       public void GetParameters_Complete2 ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       MethodAttributes.Public,
+                       CallingConventions.Standard, null);
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+               genClass.CreateType ();
+
+               ParameterInfo [] parameters = cb.GetParameters ();
+               Assert.IsNotNull (parameters, "#1");
+               Assert.AreEqual (0, parameters.Length, "#2");
+       }
+
+       [Test]
+       public void GetParameters_Incomplete ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       0, 0, new Type [2] { typeof (int), typeof (string) });
+               cb.DefineParameter (1, ParameterAttributes.In, "param1");
+               cb.DefineParameter (2, ParameterAttributes.In, "param2");
                cb.GetILGenerator ().Emit (OpCodes.Ret);
 
-               // Can't be called before CreateType ()
-               /* This does not work under mono
                try {
                        cb.GetParameters ();
-                       Fail ();
-               } catch (InvalidOperationException) {
+                       Assert.Fail ("#1");
+#if NET_2_0
+               } catch (NotSupportedException ex) {
+                       // Type has not been created
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
                }
-               */
+#else
+               } catch (InvalidOperationException ex) {
+                       // Type has not been created
+                       Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
+#endif
+       }
 
-               tb.CreateType ();
+       [Test]
+       public void GetToken ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       0, 0, new Type [1] { typeof(int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
 
-               /* This does not work under MS.NET !
-               cb.GetParameters ();
-               */
+               MethodToken tokenA = cb.GetToken ();
+#if NET_2_0
+               Assert.IsFalse (tokenA == MethodToken.Empty, "#1");
+#else
+               Assert.IsFalse (tokenA.Token == MethodToken.Empty.Token, "#1");
+#endif
+
+               genClass.CreateType ();
+
+               MethodToken tokenB = cb.GetToken ();
+#if NET_2_0
+               Assert.AreEqual (tokenA, tokenB, "#2");
+#else
+               Assert.AreEqual (tokenA.Token, tokenB.Token, "#2");
+#endif
        }
 
-       public void TestGetToken () {
-               TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
-               ConstructorBuilder cb = tb.DefineConstructor (
-                        0, 0, new Type [1] {typeof(void)});
+       [Test] // Invoke (Object [])
+       public void Invoke1 ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                       0, 0, new Type [1] { typeof(int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               try {
+                       cb.Invoke (new object [1] { 42 });
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+               }
 
-               cb.GetToken ();
+               genClass.CreateType ();
+
+               try {
+                       cb.Invoke (new object [1] { 42 });
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
+               }
        }
 
-       public void TestInvoke () {
+       [Test] // Invoke (Object, Object [])
+       public void Invoke2 ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
-                        0, 0, 
-                       new Type [1] {typeof(int)});
+                        0, 0, new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
 
                try {
                        cb.Invoke (null, new object [1] { 42 });
-                       Fail ();
-               } catch (NotSupportedException) {
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
                }
 
+               genClass.CreateType ();
+
+               try {
+                       cb.Invoke (null, new object [1] { 42 });
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
+               }
+       }
+
+       [Test] // Invoke (BindingFlags, Binder, Object [], CultureInfo)
+       public void Invoke3 ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        0, 0, new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               try {
+                       cb.Invoke (0, null, new object [1] { 42 }, null);
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+               }
+
+               genClass.CreateType ();
+
+               try {
+                       cb.Invoke (0, null, new object [1] { 42 }, null);
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
+               }
+       }
+
+       [Test] // Invoke (Object, BindingFlags, Binder, Object [], CultureInfo)
+       public void Invoke4 ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        0, 0, new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               try {
+                       cb.Invoke (null, 0, null, new object [1] { 42 }, null);
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+               }
+
+               genClass.CreateType ();
+
                try {
                        cb.Invoke (null, 0, null, new object [1] { 42 }, null);
-                       Fail ();
-               } catch (NotSupportedException) {
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
                }
        }
 
-       public void TestIsDefined () {
+       [Test]
+       public void IsDefined ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
                         0, 0, 
                        new Type [1] {typeof(int)});
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               try {
+                       cb.IsDefined (null, true);
+                       Assert.Fail ("#A1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+               }
+
+               genClass.CreateType ();
 
                try {
                        cb.IsDefined (null, true);
-                       Fail ();
-               } catch (NotSupportedException) {
+                       Assert.Fail ("#B1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
                }
        }
 
-       public void TestSetCustomAttribute () {
-               TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
-               ConstructorBuilder cb = tb.DefineConstructor (
-                        0, 0, 
-                       new Type [1] {typeof(int)});
+       [Test]
+       public void TestSetCustomAttribute ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        0, 0, new Type [1] {typeof(int)});
                cb.GetILGenerator ().Emit (OpCodes.Ret);
 
                // Null argument
                try {
                        cb.SetCustomAttribute (null);
-                       Fail ();
-               } catch (ArgumentNullException) {
+                       Assert.Fail ("#A1");
+               } catch (ArgumentNullException ex) {
+                       Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                       Assert.IsNull (ex.InnerException, "#A3");
+                       Assert.IsNotNull (ex.Message, "#A4");
+                       Assert.AreEqual ("customBuilder", ex.ParamName, "#A5");
                }
 
                byte[] custAttrData = { 1, 0, 0, 0, 0};
@@ -301,22 +640,30 @@ public class ConstructorBuilderTest : Assertion
 
                // Null arguments again
                try {
-                       cb.SetCustomAttribute (null, new byte[2]);
-                       Fail ();
-               } catch (ArgumentNullException) {
+                       cb.SetCustomAttribute (null, new byte [2]);
+                       Assert.Fail ("#B1");
+               } catch (ArgumentNullException ex) {
+                       Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
+                       Assert.IsNull (ex.InnerException, "#B3");
+                       Assert.IsNotNull (ex.Message, "#B4");
+                       Assert.AreEqual ("con", ex.ParamName, "#B5");
                }
 
                try {
                        cb.SetCustomAttribute (ctorInfo, null);
-                       Fail ();
-               } catch (ArgumentNullException) {
+                       Assert.Fail ("#C1");
+               } catch (ArgumentNullException ex) {
+                       Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#C2");
+                       Assert.IsNull (ex.InnerException, "#C3");
+                       Assert.IsNotNull (ex.Message, "#C4");
+                       Assert.AreEqual ("binaryAttribute", ex.ParamName, "#C5");
                }
        }
 
        [Test]
-       public void GetCustomAttributes () {
-               TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
-               ConstructorBuilder cb = tb.DefineConstructor (
+       public void GetCustomAttributes_Emitted ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
                         MethodAttributes.Public, 0, 
                        new Type [1] {typeof(int)});
                cb.GetILGenerator ().Emit (OpCodes.Ret);
@@ -327,34 +674,137 @@ public class ConstructorBuilderTest : Assertion
 
                cb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
 
-               Type t = tb.CreateType ();
+               Type t = genClass.CreateType ();
 
                // Try the created type
                {
                        ConstructorInfo ci = t.GetConstructors () [0];
                        object[] attrs = ci.GetCustomAttributes (true);
 
-                       AssertEquals (1, attrs.Length);
-                       Assert (attrs [0] is ObsoleteAttribute);
-                       AssertEquals ("FOO", ((ObsoleteAttribute)attrs [0]).Message);
+                       Assert.AreEqual (1, attrs.Length, "#A1");
+                       Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#A2");
+                       Assert.AreEqual ("FOO", ((ObsoleteAttribute)attrs [0]).Message, "#A3");
                }
 
                // Try the type builder
                {
-                       ConstructorInfo ci = tb.GetConstructors () [0];
+                       ConstructorInfo ci = genClass.GetConstructors () [0];
                        object[] attrs = ci.GetCustomAttributes (true);
 
-                       AssertEquals (1, attrs.Length);
-                       Assert (attrs [0] is ObsoleteAttribute);
-                       AssertEquals ("FOO", ((ObsoleteAttribute)attrs [0]).Message);
+                       Assert.AreEqual (1, attrs.Length, "#B1");
+                       Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#B2");
+                       Assert.AreEqual ("FOO", ((ObsoleteAttribute)attrs [0]).Message, "#B3");
                }
+       }
 
+       [Test] // GetCustomAttributes (Boolean)
+       public void GetCustomAttributes1_Complete ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        MethodAttributes.Public, 0,
+                       new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               Type attrType = typeof (ObsoleteAttribute);
+               ConstructorInfo ctorInfo =
+                       attrType.GetConstructor (new Type [] { typeof (String) });
+               cb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
+
+               genClass.CreateType ();
+
+               try {
+                       cb.GetCustomAttributes (false);
+                       Assert.Fail ("#1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
+       }
+
+       [Test] // GetCustomAttributes (Boolean)
+       public void GetCustomAttributes1_Incomplete ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        MethodAttributes.Public, 0,
+                       new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               Type attrType = typeof (ObsoleteAttribute);
+               ConstructorInfo ctorInfo =
+                       attrType.GetConstructor (new Type [] { typeof (String) });
+               cb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
+
+               try {
+                       cb.GetCustomAttributes (false);
+                       Assert.Fail ("#1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
+       }
+
+       [Test] // GetCustomAttributes (Type, Boolean)
+       public void GetCustomAttributes2_Complete ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        MethodAttributes.Public, 0,
+                       new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               Type attrType = typeof (ObsoleteAttribute);
+               ConstructorInfo ctorInfo =
+                       attrType.GetConstructor (new Type [] { typeof (String) });
+               cb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
+
+               genClass.CreateType ();
+
+               try {
+                       cb.GetCustomAttributes (attrType, false);
+                       Assert.Fail ("#1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
+       }
+
+       [Test] // GetCustomAttributes (Type, Boolean)
+       public void GetCustomAttributes2_Incomplete ()
+       {
+               ConstructorBuilder cb = genClass.DefineConstructor (
+                        MethodAttributes.Public, 0,
+                       new Type [1] { typeof (int) });
+               cb.GetILGenerator ().Emit (OpCodes.Ret);
+
+               Type attrType = typeof (ObsoleteAttribute);
+               ConstructorInfo ctorInfo =
+                       attrType.GetConstructor (new Type [] { typeof (String) });
+               cb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
+
+               try {
+                       cb.GetCustomAttributes (attrType, false);
+                       Assert.Fail ("#1");
+               } catch (NotSupportedException ex) {
+                       // The invoked member is not supported in a dynamic
+                       // module
+                       Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
        }
 
        // Same as in MethodBuilderTest
        [Test]
-       [ExpectedException (typeof (InvalidOperationException))]
-       public void TestAddDeclarativeSecurityAlreadyCreated () {
+       public void AddDeclarativeSecurity_Complete ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
                         MethodAttributes.Public, 0, new Type [0]);
                ILGenerator ilgen = cb.GetILGenerator ();
@@ -362,19 +812,36 @@ public class ConstructorBuilderTest : Assertion
                genClass.CreateType ();
 
                PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
-               cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+               try {
+                       cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+                       Assert.Fail ("#1");
+               } catch (InvalidOperationException ex) {
+                       // Type has not been created
+                       Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
        }
 
        [Test]
-       [ExpectedException (typeof (ArgumentNullException))]
-       public void TestAddDeclarativeSecurityNullPermissionSet () {
+       public void AddDeclarativeSecurity_PSet_Null ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
                         MethodAttributes.Public, 0, new Type [0]);
-               cb.AddDeclarativeSecurity (SecurityAction.Demand, null);
+               try {
+                       cb.AddDeclarativeSecurity (SecurityAction.Demand, null);
+                       Assert.Fail ("#1");
+               } catch (ArgumentNullException ex) {
+                       Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+                       Assert.AreEqual ("pset", ex.ParamName, "#5");
+               }
        }
 
        [Test]
-       public void TestAddDeclarativeSecurityInvalidAction () {
+       public void AddDeclarativeSecurity_Action_Invalid ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
                         MethodAttributes.Public, 0, new Type [0]);
 
@@ -387,20 +854,32 @@ public class ConstructorBuilderTest : Assertion
                foreach (SecurityAction action in actions) {
                        try {
                                cb.AddDeclarativeSecurity (action, set);
-                               Fail ();
-                       } catch (ArgumentOutOfRangeException) {
+                               Assert.Fail ("#1");
+                       } catch (ArgumentOutOfRangeException ex) {
+                               Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.ActualValue, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("action", ex.ParamName, "#5");
                        }
                }
        }
 
        [Test]
-       [ExpectedException (typeof (InvalidOperationException))]
-       public void TestAddDeclarativeSecurityDuplicateAction () {
+       public void AddDeclarativeSecurity_Action_Duplicate ()
+       {
                ConstructorBuilder cb = genClass.DefineConstructor (
                         MethodAttributes.Public, 0, new Type [0]);
                PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
                cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
-               cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+               try {
+                       cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+                       Assert.Fail ("#1");
+               } catch (InvalidOperationException ex) {
+                       // Type has not been created
+                       Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                       Assert.IsNull (ex.InnerException, "#3");
+                       Assert.IsNotNull (ex.Message, "#4");
+               }
        }
 }
 }
diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ConstructorOnTypeBuilderInstTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ConstructorOnTypeBuilderInstTest.cs
new file mode 100644 (file)
index 0000000..5f45f02
--- /dev/null
@@ -0,0 +1,449 @@
+//
+// MethodOnTypeBuilderInstTest - NUnit Test Cases for MethodOnTypeBuilderInst
+//
+// Author:
+//   Gert Driesen (drieseng@users.sourceforge.net)
+//
+// Copyright (C) 2008 Gert Driesen
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+
+using NUnit.Framework;
+
+namespace MonoTests.System.Reflection.Emit
+{
+       [TestFixture]
+       public class ConstructorOnTypeBuilderInstTest
+       {
+               private static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.ConstructorOnTypeBuilderInstTest";
+
+               private AssemblyBuilder assembly;
+               private ModuleBuilder module;
+               private Type typeBarOfInt32;
+               private ConstructorInfo ci;
+               private TypeBuilder tb;
+
+               [SetUp]
+               public void SetUp ()
+               {
+                       AssemblyName assemblyName = new AssemblyName ();
+                       assemblyName.Name = ASSEMBLY_NAME;
+
+                       assembly = AppDomain.CurrentDomain.DefineDynamicAssembly (
+                               assemblyName, AssemblyBuilderAccess.RunAndSave,
+                               Path.GetTempPath ());
+
+                       module = assembly.DefineDynamicModule ("module1");
+
+                       tb = module.DefineType ("Bar");
+                       GenericTypeParameterBuilder [] typeParams = tb.DefineGenericParameters ("T");
+
+                       ConstructorBuilder cb = tb.DefineConstructor (MethodAttributes.Public,
+                               CallingConventions.Standard,
+                               new Type [] { typeof (string), typeof (int) });
+                       ILGenerator ig = cb.GetILGenerator ();
+                       ig.Emit (OpCodes.Ret);
+
+                       typeBarOfInt32 = tb.MakeGenericType (typeof (int));
+                       ci = TypeBuilder.GetConstructor (typeBarOfInt32, cb);
+               }
+
+               [Test]
+               [Category ("NotWorking")]
+               public void Attributes ()
+               {
+                       Assert.AreEqual (MethodAttributes.PrivateScope |
+                               MethodAttributes.Public | MethodAttributes.SpecialName,
+                               ci.Attributes, "#1");
+                       tb.CreateType ();
+                       Assert.AreEqual (MethodAttributes.PrivateScope |
+                               MethodAttributes.Public | MethodAttributes.SpecialName,
+                               ci.Attributes, "#2");
+               }
+
+               [Test]
+               [Category ("NotWorking")]
+               public void CallingConvention ()
+               {
+                       Assert.AreEqual (CallingConventions.HasThis,
+                               ci.CallingConvention, "#1");
+                       tb.CreateType ();
+                       Assert.AreEqual (CallingConventions.HasThis,
+                               ci.CallingConvention, "#2");
+               }
+
+               [Test]
+               public void ContainsGenericParameters ()
+               {
+                       Assert.IsFalse (ci.ContainsGenericParameters, "#1");
+                       tb.CreateType ();
+                       Assert.IsFalse (ci.ContainsGenericParameters, "#2");
+               }
+
+               [Test]
+               public void DeclaringType ()
+               {
+                       Assert.AreSame (typeBarOfInt32, ci.DeclaringType, "#1");
+                       tb.CreateType ();
+                       Assert.AreSame (typeBarOfInt32, ci.DeclaringType, "#2");
+               }
+
+               [Test] // GetCustomAttributes (Boolean)
+               public void GetCustomAttributes1 ()
+               {
+                       try {
+                               ci.GetCustomAttributes (false);
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.GetCustomAttributes (false);
+                               Assert.Fail ("#B1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test] // GetCustomAttributes (Type, Boolean)
+               public void GetCustomAttributes2 ()
+               {
+                       try {
+                               ci.GetCustomAttributes (typeof (FlagsAttribute), false);
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.GetCustomAttributes (typeof (FlagsAttribute), false);
+                               Assert.Fail ("#B1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test]
+               public void GetGenericArguments ()
+               {
+                       try {
+                               ci.GetGenericArguments ();
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // Derived classes must provide an implementation
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.GetGenericArguments ();
+                               Assert.Fail ("#B1");
+                       } catch (NotSupportedException ex) {
+                               // Derived classes must provide an implementation
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test]
+               public void GetMethodImplementationFlags ()
+               {
+                       Assert.AreEqual (MethodImplAttributes.Managed,
+                               ci.GetMethodImplementationFlags (), "#1");
+                       tb.CreateType ();
+                       Assert.AreEqual (MethodImplAttributes.Managed,
+                               ci.GetMethodImplementationFlags (), "#2");
+               }
+
+               [Test]
+               public void GetParameters ()
+               {
+                       try {
+                               ci.GetParameters ();
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // Type has not been created
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       ParameterInfo [] parameters = ci.GetParameters ();
+                       Assert.IsNotNull (parameters, "#B1");
+                       Assert.AreEqual (2, parameters.Length, "#B2");
+
+                       Assert.AreEqual (ParameterAttributes.None, parameters [0].Attributes, "#C1");
+                       Assert.IsNull (parameters [0].Name, "#C2");
+                       Assert.AreEqual (typeof (string), parameters [0].ParameterType, "#C3");
+                       Assert.AreEqual (0, parameters [0].Position, "#C4");
+
+                       Assert.AreEqual (ParameterAttributes.None, parameters [1].Attributes, "#D1");
+                       Assert.IsNull (parameters [1].Name, "#D2");
+                       Assert.AreEqual (typeof (int), parameters [1].ParameterType, "#D3");
+                       Assert.AreEqual (1, parameters [1].Position, "#D4");
+               }
+
+               [Test] // Invoke (Object [])
+               public void Invoke1 ()
+               {
+                       try {
+                               ci.Invoke (new object [0]);
+                               Assert.Fail ("#A1");
+                       } catch (InvalidOperationException ex) {
+                               // Operation is not valid due to the current
+                               // state of the object
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.Invoke (new object [0]);
+                               Assert.Fail ("#B1");
+                       } catch (InvalidOperationException ex) {
+                               // Operation is not valid due to the current
+                               // state of the object
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test] // Invoke (Object, Object [])
+               public void Invoke2 ()
+               {
+                       try {
+                               ci.Invoke (null, new object [0]);
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // Specified method is not supported
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.Invoke (null, new object [0]);
+                               Assert.Fail ("#B1");
+                       } catch (NotSupportedException ex) {
+                               // Specified method is not supported
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test] // Invoke (BindingFlags, Binder, Object [], CultureInfo)
+               public void Invoke3 ()
+               {
+                       try {
+                               ci.Invoke (BindingFlags.Default, null, new object [0],
+                                       CultureInfo.InvariantCulture);
+                               Assert.Fail ("#A1");
+                       } catch (InvalidOperationException ex) {
+                               // Operation is not valid due to the current
+                               // state of the object
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.Invoke (BindingFlags.Default, null, new object [0],
+                                       CultureInfo.InvariantCulture);
+                               Assert.Fail ("#B1");
+                       } catch (InvalidOperationException ex) {
+                               // Operation is not valid due to the current
+                               // state of the object
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test] // Invoke (Object, BindingFlags, Binder, Object [], CultureInfo)
+               public void Invoke4 ()
+               {
+                       try {
+                               ci.Invoke (null, BindingFlags.Default, null,
+                                       new object [0], CultureInfo.InvariantCulture);
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // Specified method is not supported
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.Invoke (null, BindingFlags.Default, null,
+                                       new object [0], CultureInfo.InvariantCulture);
+                               Assert.Fail ("#B1");
+                       } catch (NotSupportedException ex) {
+                               // Specified method is not supported
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test]
+               public void IsDefined ()
+               {
+                       try {
+                               ci.IsDefined (typeof (FlagsAttribute), false);
+                               Assert.Fail ("#A1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               ci.IsDefined (typeof (FlagsAttribute), false);
+                               Assert.Fail ("#B1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test]
+               public void IsGenericMethodDefinition ()
+               {
+                       Assert.IsFalse (ci.IsGenericMethodDefinition, "#1");
+                       tb.CreateType ();
+                       Assert.IsFalse (ci.IsGenericMethodDefinition, "#2");
+               }
+
+               [Test]
+               public void IsGenericMethod ()
+               {
+                       Assert.IsFalse (ci.IsGenericMethod, "#1");
+                       tb.CreateType ();
+                       Assert.IsFalse (ci.IsGenericMethod, "#2");
+               }
+
+               [Test]
+               public void MemberType ()
+               {
+                       Assert.AreEqual (MemberTypes.Constructor, ci.MemberType, "#1");
+                       tb.CreateType ();
+                       Assert.AreEqual (MemberTypes.Constructor, ci.MemberType, "#2");
+               }
+
+               [Test]
+               public void MethodHandle ()
+               {
+                       try {
+                               RuntimeMethodHandle handle = ci.MethodHandle;
+                               Assert.Fail ("#A1:" + handle);
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                       }
+
+                       tb.CreateType ();
+
+                       try {
+                               RuntimeMethodHandle handle = ci.MethodHandle;
+                               Assert.Fail ("#B1:" + handle);
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                       }
+               }
+
+               [Test]
+               public void Module ()
+               {
+                       Assert.AreSame (module, ci.Module, "#1");
+                       tb.CreateType ();
+                       Assert.AreSame (module, ci.Module, "#2");
+               }
+
+               [Test]
+               public void Name ()
+               {
+                       Assert.AreEqual (".ctor", ci.Name, "#1");
+                       tb.CreateType ();
+                       Assert.AreEqual (".ctor", ci.Name, "#2");
+               }
+
+               [Test]
+               public void ReflectedType ()
+               {
+                       Assert.AreSame (typeBarOfInt32, ci.ReflectedType, "#1");
+                       tb.CreateType ();
+                       Assert.AreSame (typeBarOfInt32, ci.ReflectedType, "#2");
+               }
+       }
+}
+
+#endif
index 0144bad888ca364df36d35351cfef0522d0dca24..6ef86d8af1e47c33afc02d549559f4e781cd2671 100644 (file)
@@ -187,7 +187,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_create.GetCustomAttributes (false);
                                Assert.Fail ("#A1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
                                Assert.IsNull (ex.InnerException, "#A3");
                                Assert.IsNotNull (ex.Message, "#A4");
@@ -197,7 +197,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_edit.GetCustomAttributes (false);
                                Assert.Fail ("#B1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
                                Assert.IsNull (ex.InnerException, "#B3");
                                Assert.IsNotNull (ex.Message, "#B4");
@@ -212,7 +212,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_create.GetCustomAttributes (typeof (FlagsAttribute), false);
                                Assert.Fail ("#A1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
                                Assert.IsNull (ex.InnerException, "#A3");
                                Assert.IsNotNull (ex.Message, "#A4");
@@ -222,7 +222,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_edit.GetCustomAttributes (typeof (FlagsAttribute), false);
                                Assert.Fail ("#B1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
                                Assert.IsNull (ex.InnerException, "#B3");
                                Assert.IsNotNull (ex.Message, "#B4");
@@ -278,7 +278,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_create.GetParameters ();
                                Assert.Fail ("#A1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // Type has not been created
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
                                Assert.IsNull (ex.InnerException, "#A3");
                                Assert.IsNotNull (ex.Message, "#A4");
@@ -288,7 +288,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_edit.GetParameters ();
                                Assert.Fail ("#B1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // Type has not been created
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
                                Assert.IsNull (ex.InnerException, "#B3");
                                Assert.IsNotNull (ex.Message, "#B4");
@@ -330,7 +330,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_create.IsDefined (typeof (FlagsAttribute), false);
                                Assert.Fail ("#A1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
                                Assert.IsNull (ex.InnerException, "#A3");
                                Assert.IsNotNull (ex.Message, "#A4");
@@ -340,7 +340,7 @@ namespace MonoTests.System.Reflection.Emit
                                method_edit.IsDefined (typeof (FlagsAttribute), false);
                                Assert.Fail ("#B1");
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
                                Assert.IsNull (ex.InnerException, "#B3");
                                Assert.IsNotNull (ex.Message, "#B4");
@@ -399,7 +399,7 @@ namespace MonoTests.System.Reflection.Emit
                                RuntimeMethodHandle handle = method_create.MethodHandle;
                                Assert.Fail ("#A1:" + handle);
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
                                Assert.IsNull (ex.InnerException, "#A3");
                                Assert.IsNotNull (ex.Message, "#A4");
@@ -409,7 +409,7 @@ namespace MonoTests.System.Reflection.Emit
                                RuntimeMethodHandle handle = method_edit.MethodHandle;
                                Assert.Fail ("#B1:" + handle);
                        } catch (NotSupportedException ex) {
-                               // Specified method is not supported
+                               // The invoked member is not supported in a dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
                                Assert.IsNull (ex.InnerException, "#B3");
                                Assert.IsNotNull (ex.Message, "#B4");
index 1819e23eff8fe142d5c4fb91dfa262d948a80bb8..130c776dc50ae4b90e3b1c716ee13d6be6f0325e 100644 (file)
@@ -132,7 +132,59 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               public void TestDefineType_InterfaceNotAbstract ()
+               public void DefineType_Name_Null ()
+               {
+                       AssemblyBuilder ab = genAssembly ();
+                       ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll", true);
+                       try {
+                               mb.DefineType ((string) null);
+                               Assert.Fail ("#1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("fullname", ex.ParamName, "#5");
+                       }
+               }
+
+               [Test]
+               public void DefineType_Name_Empty ()
+               {
+                       AssemblyBuilder ab = genAssembly ();
+                       ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll", true);
+                       try {
+                               mb.DefineType (string.Empty);
+                               Assert.Fail ("#1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("fullname", ex.ParamName, "#5");
+                       }
+               }
+
+               [Test]
+               public void DefineType_Name_NullChar ()
+               {
+                       AssemblyBuilder ab = genAssembly ();
+                       ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll", true);
+                       try {
+                               mb.DefineType ("\0test");
+                               Assert.Fail ("#1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("fullname", ex.ParamName, "#5");
+                       }
+
+                       mb.DefineType ("te\0st");
+               }
+
+               [Test]
+               public void DefineType_InterfaceNotAbstract ()
                {
                        AssemblyBuilder ab = genAssembly ();
                        ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll", true);
@@ -265,9 +317,9 @@ namespace MonoTests.System.Reflection.Emit
                {
                        AssemblyBuilder ab = genAssembly ();
                        ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll");
-                       
-            TypeBuilder tb1 = mb.DefineType("Foo", TypeAttributes.Public);
-                       
+
+                       TypeBuilder tb1 = mb.DefineType("Foo", TypeAttributes.Public);
+
                        Type[] types = mb.GetTypes ();
                        Assert.AreEqual (1, types.Length);
                        Assert.AreEqual (tb1, types [0]);
index b7399b0fb93b086919a81d213e058d435ae9913b..c249fea3ec43f4a02cda69c141a79ebf8a0bcb94 100644 (file)
@@ -163,11 +163,17 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGUIDIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       Guid g = tb.GUID;
+                       try {
+                               Guid g = tb.GUID;
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test] // bug #71302
@@ -211,6 +217,8 @@ namespace MonoTests.System.Reflection.Emit
                                bool b = tb.HasElementType;
                                Assert.Fail ("#1: " + b);
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -235,6 +243,8 @@ namespace MonoTests.System.Reflection.Emit
                                bool b = tb.HasElementType;
                                Assert.Fail ("#1: " + b);
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -902,8 +912,7 @@ namespace MonoTests.System.Reflection.Emit
                                Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
                                Assert.IsNull (ex.InnerException, "#A3");
                                Assert.IsNotNull (ex.Message, "#A4");
-                               Assert.IsNotNull (ex.ParamName, "#A5");
-                               Assert.AreEqual ("parent", ex.ParamName, "#A6");
+                               Assert.AreEqual ("parent", ex.ParamName, "#A5");
                        }
 #endif
 
@@ -920,8 +929,7 @@ namespace MonoTests.System.Reflection.Emit
                                Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
                                Assert.IsNull (ex.InnerException, "#B3");
                                Assert.IsNotNull (ex.Message, "#B4");
-                               Assert.IsNotNull (ex.ParamName, "#B5");
-                               Assert.AreEqual ("parent", ex.ParamName, "#B6");
+                               Assert.AreEqual ("parent", ex.ParamName, "#B5");
                        }
 #endif
 
@@ -976,12 +984,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void TestSetParentComplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        tb.CreateType ();
-                       tb.SetParent (typeof (Attribute));
+                       try {
+                               tb.SetParent (typeof (Attribute));
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -1002,19 +1017,35 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestTypeHandle ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       RuntimeTypeHandle handle = tb.TypeHandle;
+                       try {
+                               RuntimeTypeHandle handle = tb.TypeHandle;
+                               Assert.Fail ("#1:" + handle);
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestTypeInitializerIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       ConstructorInfo cb = tb.TypeInitializer;
+                       try {
+                               ConstructorInfo cb = tb.TypeInitializer;
+                               Assert.Fail ("#1:" + (cb != null));
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -1063,15 +1094,24 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               public void TestAddInterfaceImplementation ()
+               public void AddInterfaceImplementation_InterfaceType_Null ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        try {
                                tb.AddInterfaceImplementation (null);
                                Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("interfaceType", ex.ParamName, "#5");
                        }
+               }
 
+               [Test]
+               public void TestAddInterfaceImplementation ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
                        tb.AddInterfaceImplementation (typeof (AnInterface));
                        tb.AddInterfaceImplementation (typeof (AnInterface));
 
@@ -1132,8 +1172,12 @@ namespace MonoTests.System.Reflection.Emit
                        // Can not be called on a created type
                        try {
                                tb.DefineConstructor (0, 0, null);
-                               Assert.Fail ();
-                       } catch (InvalidOperationException) {
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
                        }
                }
 
@@ -1147,19 +1191,24 @@ namespace MonoTests.System.Reflection.Emit
                        // Can not be called on a created type, altough the MSDN docs does not mention this
                        try {
                                tb.DefineDefaultConstructor (0);
-                               Assert.Fail ();
-                       } catch (InvalidOperationException) {
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
                        }
                }
-
+       
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void TestDefineDefaultConstructorParent ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.DefineConstructor (MethodAttributes.Public,
+                       ConstructorBuilder cb = tb.DefineConstructor (
+                               MethodAttributes.Public,
                                CallingConventions.Standard,
                                new Type [] { typeof (string) });
+                       cb.GetILGenerator ().Emit (OpCodes.Ret);
                        Type type = tb.CreateType ();
 
                        // create TypeBuilder for type that derived from the 
@@ -1169,7 +1218,38 @@ namespace MonoTests.System.Reflection.Emit
 
                        // you cannot create a type with a default ctor that
                        // derives from a type without a default ctor
-                       tb.CreateType ();
+                       try {
+                               tb.CreateType ();
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // Parent does not have a default constructor.
+                               // The default constructor must be explicitly defined
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
+               }
+
+               [Test]
+               public void DefineEvent_Name_NullChar ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+
+                       try {
+                               tb.DefineEvent ("\0test", EventAttributes.None,
+                                       typeof (int));
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
+                       }
+
+                       EventBuilder eb = tb.DefineEvent ("te\0st", EventAttributes.None,
+                               typeof (int));
+                       Assert.IsNotNull (eb, "#B1");
                }
 
                [Test]
@@ -1180,31 +1260,72 @@ namespace MonoTests.System.Reflection.Emit
                        // Test invalid arguments
                        try {
                                tb.DefineEvent (null, 0, typeof (int));
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
                        }
 
                        try {
                                tb.DefineEvent ("FOO", 0, null);
-                               Assert.Fail ("#2");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.AreEqual ("type", ex.ParamName, "#B5");
                        }
 
                        try {
-                               tb.DefineEvent ("", 0, typeof (int));
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               tb.DefineEvent (string.Empty, 0, typeof (int));
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
+                               Assert.IsNull (ex.InnerException, "#C3");
+                               Assert.IsNotNull (ex.Message, "#C4");
+                               Assert.AreEqual ("name", ex.ParamName, "#C5");
                        }
 
                        tb.CreateType ();
+
                        // Can not be called on a created type
                        try {
                                tb.DefineEvent ("BAR", 0, typeof (int));
-                               Assert.Fail ("#4");
-                       } catch (InvalidOperationException) {
+                               Assert.Fail ("#D1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#D2");
+                               Assert.IsNull (ex.InnerException, "#D3");
+                               Assert.IsNotNull (ex.Message, "#D4");
                        }
                }
 
+               [Test]
+               public void DefineField_Name_NullChar ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+
+                       try {
+                               tb.DefineField ("\0test", typeof (int),
+                                       FieldAttributes.Private);
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("fieldName", ex.ParamName, "#A5");
+                       }
+
+                       FieldBuilder fb = tb.DefineField ("te\0st", typeof (int),
+                               FieldAttributes.Private);
+                       Assert.IsNotNull (fb, "#B1");
+                       Assert.AreEqual ("te\0st", fb.Name, "#B2");
+               }
+
                [Test]
                public void TestDefineField ()
                {
@@ -1213,36 +1334,60 @@ namespace MonoTests.System.Reflection.Emit
                        // Check invalid arguments
                        try {
                                tb.DefineField (null, typeof (int), 0);
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("fieldName", ex.ParamName, "#A5");
                        }
 
                        try {
-                               tb.DefineField ("", typeof (int), 0);
-                               Assert.Fail ("#2");
-                       } catch (ArgumentException) {
+                               tb.DefineField (string.Empty, typeof (int), 0);
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.AreEqual ("fieldName", ex.ParamName, "#B5");
                        }
 
                        try {
                                // Strangely, 'A<NULL>' is accepted...
                                string name = String.Format ("{0}", (char) 0);
                                tb.DefineField (name, typeof (int), 0);
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
+                               Assert.IsNull (ex.InnerException, "#C3");
+                               Assert.IsNotNull (ex.Message, "#C4");
+                               Assert.AreEqual ("fieldName", ex.ParamName, "#C5");
                        }
 
                        try {
                                tb.DefineField ("A", typeof (void), 0);
-                               Assert.Fail ("#4");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#D1");
+                       } catch (ArgumentException ex) {
+                               // Bad field type in defining field
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#D2");
+                               Assert.IsNull (ex.InnerException, "#D3");
+                               Assert.IsNotNull (ex.Message, "#D4");
+                               Assert.IsNull (ex.ParamName, "#D5");
                        }
 
                        tb.CreateType ();
+
                        // Can not be called on a created type
                        try {
                                tb.DefineField ("B", typeof (int), 0);
-                               Assert.Fail ("#5");
-                       } catch (InvalidOperationException) {
+                               Assert.Fail ("#E1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#E2");
+                               Assert.IsNull (ex.InnerException, "#E3");
+                               Assert.IsNotNull (ex.Message, "#E4");
                        }
                }
 
@@ -1254,34 +1399,57 @@ namespace MonoTests.System.Reflection.Emit
                        // Check invalid arguments
                        try {
                                tb.DefineInitializedData (null, new byte [1], 0);
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
                        }
 
                        try {
                                tb.DefineInitializedData ("FOO", null, 0);
-                               Assert.Fail ("#2");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.AreEqual ("data", ex.ParamName, "#B5");
                        }
 
                        try {
-                               tb.DefineInitializedData ("", new byte [1], 0);
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               tb.DefineInitializedData (string.Empty, new byte [1], 0);
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
+                               Assert.IsNull (ex.InnerException, "#C3");
+                               Assert.IsNotNull (ex.Message, "#C4");
+                               Assert.AreEqual ("name", ex.ParamName, "#C5");
                        }
 
                        // The size of the data is less than or equal to zero ???
                        try {
                                tb.DefineInitializedData ("BAR", new byte [0], 0);
-                               Assert.Fail ("#4");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#D1");
+                       } catch (ArgumentException ex) {
+                               // Data size must be > 0 and < 0x3f0000
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#D2");
+                               Assert.IsNull (ex.InnerException, "#D3");
+                               Assert.IsNotNull (ex.Message, "#D4");
+                               Assert.IsNull (ex.ParamName, "#D5");
                        }
 
                        try {
                                string name = String.Format ("{0}", (char) 0);
                                tb.DefineInitializedData (name, new byte [1], 0);
-                               Assert.Fail ("#5");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#E1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#E2");
+                               Assert.IsNull (ex.InnerException, "#E3");
+                               Assert.IsNotNull (ex.Message, "#E4");
+                               Assert.AreEqual ("fieldName", ex.ParamName, "#E5");
                        }
 
                        tb.CreateType ();
@@ -1289,8 +1457,12 @@ namespace MonoTests.System.Reflection.Emit
                        // Can not be called on a created type, altough the MSDN docs does not mention this
                        try {
                                tb.DefineInitializedData ("BAR2", new byte [1], 0);
-                               Assert.Fail ("#6");
-                       } catch (InvalidOperationException) {
+                               Assert.Fail ("#F1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#F2");
+                               Assert.IsNull (ex.InnerException, "#F3");
+                               Assert.IsNotNull (ex.Message, "#F4");
                        }
                }
 
@@ -1301,38 +1473,64 @@ namespace MonoTests.System.Reflection.Emit
 
                        try {
                                tb.DefineUninitializedData (null, 1, 0);
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
                        }
 
                        try {
-                               tb.DefineUninitializedData ("", 1, 0);
-                               Assert.Fail ("#2");
-                       } catch (ArgumentException) {
+                               tb.DefineUninitializedData (string.Empty, 1, 0);
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.AreEqual ("name", ex.ParamName, "#B5");
                        }
 
                        // The size of the data is less than or equal to zero ???
                        try {
                                tb.DefineUninitializedData ("BAR", 0, 0);
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // Data size must be > 0 and < 0x3f0000
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
+                               Assert.IsNull (ex.InnerException, "#C3");
+                               Assert.IsNotNull (ex.Message, "#C4");
+                               Assert.IsNull (ex.ParamName, "#C5");
                        }
 
                        try {
                                string name = String.Format ("{0}", (char) 0);
                                tb.DefineUninitializedData (name, 1, 0);
-                               Assert.Fail ("#4");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#D1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#D2");
+                               Assert.IsNull (ex.InnerException, "#D3");
+                               Assert.IsNotNull (ex.Message, "#D4");
+                               Assert.AreEqual ("fieldName", ex.ParamName, "#D5");
                        }
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void DefineUninitializedDataAlreadyCreated ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        tb.CreateType ();
-                       tb.DefineUninitializedData ("BAR2", 1, 0);
+                       try {
+                               tb.DefineUninitializedData ("BAR2", 1, 0);
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -1355,6 +1553,28 @@ namespace MonoTests.System.Reflection.Emit
                        Marshal.FreeHGlobal (ptr);
                }
 
+               [Test]
+               public void DefineMethod_Name_NullChar ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+                       try {
+                               tb.DefineMethod ("\0test", MethodAttributes.Private,
+                                       typeof (string), Type.EmptyTypes);
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
+                       }
+
+                       MethodBuilder mb = tb.DefineMethod ("te\0st", MethodAttributes.Private,
+                               typeof (string), Type.EmptyTypes);
+                       Assert.IsNotNull (mb, "#B1");
+                       Assert.AreEqual ("te\0st", mb.Name, "#B2");
+               }
+
                [Test]
                public void TestDefineMethod ()
                {
@@ -1363,22 +1583,36 @@ namespace MonoTests.System.Reflection.Emit
                        // Check invalid arguments
                        try {
                                tb.DefineMethod (null, 0, null, null);
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
                        }
 
                        try {
-                               tb.DefineMethod ("", 0, null, null);
-                               Assert.Fail ("#2");
-                       } catch (ArgumentException) {
+                               tb.DefineMethod (string.Empty, 0, null, null);
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.AreEqual ("name", ex.ParamName, "#B5");
                        }
 
                        // Check non-virtual methods on an interface
                        TypeBuilder tb2 = module.DefineType (genTypeName (), TypeAttributes.Interface | TypeAttributes.Abstract);
                        try {
                                tb2.DefineMethod ("FOO", MethodAttributes.Abstract, null, null);
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // Interface method must be abstract and virtual
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
+                               Assert.IsNull (ex.InnerException, "#C3");
+                               Assert.IsNotNull (ex.Message, "#C4");
+                               Assert.IsNull (ex.ParamName, "#C5");
                        }
 
                        // Check static methods on an interface
@@ -1390,8 +1624,12 @@ namespace MonoTests.System.Reflection.Emit
                        // Can not be called on a created type
                        try {
                                tb.DefineMethod ("bar", 0, null, null);
-                               Assert.Fail ("#4");
-                       } catch (InvalidOperationException) {
+                               Assert.Fail ("#D1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#D2");
+                               Assert.IsNull (ex.InnerException, "#D3");
+                               Assert.IsNotNull (ex.Message, "#D4");
                        }
                }
 
@@ -1456,20 +1694,34 @@ namespace MonoTests.System.Reflection.Emit
                        // Check invalid arguments
                        try {
                                tb.DefineNestedType (null);
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("fullname", ex.ParamName, "#A5");
                        }
 
                        try {
-                               tb.DefineNestedType ("");
-                               Assert.Fail ("#2");
-                       } catch (ArgumentException) {
+                               tb.DefineNestedType (string.Empty);
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentException ex) {
+                               // Empty name is not legal
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.AreEqual ("fullname", ex.ParamName, "#B5");
                        }
 
                        try {
                                tb.DefineNestedType (nullName ());
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
+                               Assert.IsNull (ex.InnerException, "#C3");
+                               Assert.IsNotNull (ex.Message, "#C4");
+                               Assert.AreEqual ("fullname", ex.ParamName, "#C5");
                        }
 
                        // If I fix the code so this works then mcs breaks -> how can mcs
@@ -1486,8 +1738,12 @@ namespace MonoTests.System.Reflection.Emit
                        try {
                                tb.DefineNestedType ("BB", TypeAttributes.NestedPublic, null,
                                                                         new Type [1]);
-                               Assert.Fail ("#5");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#D1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#D2");
+                               Assert.IsNull (ex.InnerException, "#D3");
+                               Assert.IsNotNull (ex.Message, "#D4");
+                               Assert.AreEqual ("interfaces", ex.ParamName, "#D5");
                        }
 
                        // I think this should reject non-interfaces, but it does not
@@ -1518,15 +1774,41 @@ namespace MonoTests.System.Reflection.Emit
                        {
                                TypeBuilder nested = tb.DefineNestedType ("N1");
 
-                               Assert.AreEqual ("N1", nested.Name, "#6");
-                               Assert.AreEqual (typeof (object), nested.BaseType, "#7");
-                               Assert.AreEqual (TypeAttributes.NestedPrivate, nested.Attributes, "#8");
-                               Assert.AreEqual (0, nested.GetInterfaces ().Length, "#9");
+                               Assert.AreEqual ("N1", nested.Name, "#E1");
+                               Assert.AreEqual (typeof (object), nested.BaseType, "#E2");
+                               Assert.AreEqual (TypeAttributes.NestedPrivate, nested.Attributes, "#E3");
+                               Assert.AreEqual (0, nested.GetInterfaces ().Length, "#E4");
                        }
 
                        // TODO:
                }
 
+               [Test]
+               public void DefinePInvokeMethod_Name_NullChar ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+                       try {
+                               tb.DefinePInvokeMethod ("\0test", "B", "C",
+                                       MethodAttributes.Private, CallingConventions.Standard,
+                                       typeof (string),Type.EmptyTypes, CallingConvention.Cdecl,
+                                       CharSet.Unicode);
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
+                       }
+
+                       MethodBuilder mb = tb.DefinePInvokeMethod ("te\0st", "B", "C",
+                               MethodAttributes.Private, CallingConventions.Standard,
+                               typeof (string), Type.EmptyTypes, CallingConvention.Cdecl,
+                               CharSet.Unicode);
+                       Assert.IsNotNull (mb, "#B1");
+                       Assert.AreEqual ("te\0st", mb.Name, "#B2");
+               }
+
                [Test]
                public void TestDefinePInvokeMethod ()
                {
@@ -1537,16 +1819,26 @@ namespace MonoTests.System.Reflection.Emit
                        // Try invalid parameters
                        try {
                                tb.DefinePInvokeMethod (null, "B", "C", 0, 0, null, null, 0, 0);
-                               Assert.Fail ("#1");
-                       } catch (ArgumentNullException) {
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
                        }
                        // etc...
 
                        // Try invalid attributes
                        try {
                                tb.DefinePInvokeMethod ("A2", "B", "C", MethodAttributes.Abstract, 0, null, null, 0, 0);
-                               Assert.Fail ("#2");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#B1");
+                       } catch (ArgumentException ex) {
+                               // PInvoke methods must be static and native and
+                               // cannot be abstract
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.IsNull (ex.ParamName, "#B5");
                        }
 
                        // Try an interface parent
@@ -1554,24 +1846,60 @@ namespace MonoTests.System.Reflection.Emit
 
                        try {
                                tb2.DefinePInvokeMethod ("A", "B", "C", 0, 0, null, null, 0, 0);
-                               Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                               Assert.Fail ("#C1");
+                       } catch (ArgumentException ex) {
+                               // PInvoke methods cannot exist on interfaces
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+                               Assert.IsNull (ex.InnerException, "#B3");
+                               Assert.IsNotNull (ex.Message, "#B4");
+                               Assert.IsNull (ex.ParamName, "#B5");
                        }
                }
 
                [Test]
-               public void TestDefineProperty ()
+               public void DefineProperty_Name_NullChar ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
 
-                       // Check null parameter types
                        try {
-                               tb.DefineProperty ("A", 0, null, new Type [1]);
-                               Assert.Fail ();
-                       } catch (ArgumentNullException) {
+                               tb.DefineProperty ("\0test", 0, typeof (string), Type.EmptyTypes);
+                               Assert.Fail ("#A1");
+                       } catch (ArgumentException ex) {
+                               // Illegal name
+                               Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+                               Assert.IsNull (ex.InnerException, "#A3");
+                               Assert.IsNotNull (ex.Message, "#A4");
+                               Assert.AreEqual ("name", ex.ParamName, "#A5");
+                       }
+
+                       PropertyBuilder pb = tb.DefineProperty ("te\0st", 0,
+                               typeof (string), Type.EmptyTypes); 
+                       Assert.IsNotNull (pb, "#B1");
+                       Assert.AreEqual ("te\0st", pb.Name, "#B2");
+               }
+
+               [Test]
+               public void DefineProperty_ParameterTypes_ItemNull ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+
+                       try {
+                               tb.DefineProperty ("A", 0, typeof (string), new Type [1]);
+                               Assert.Fail ("#1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
                        }
                }
 
+               [Test]
+               public void DefineProperty_ReturnType_Null ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+                       tb.DefineProperty ("A", 0, null, Type.EmptyTypes);
+               }
+
 #if NET_2_0
                [Test]
                // Test that changes made to the method builder after a call to GetMethod ()
@@ -1640,12 +1968,20 @@ namespace MonoTests.System.Reflection.Emit
 #endif
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                [Category ("NotWorking")]
                public void TestIsDefinedIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.IsDefined (typeof (int), true);
+                       try {
+                               tb.IsDefined (typeof (int), true);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -1678,8 +2014,7 @@ namespace MonoTests.System.Reflection.Emit
                                Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
-                               Assert.IsNotNull (ex.ParamName, "#5");
-                               Assert.AreEqual ("attributeType", ex.ParamName, "#6");
+                               Assert.AreEqual ("attributeType", ex.ParamName, "#5");
                        }
                }
 
@@ -1697,6 +2032,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.GetConstructor (Type.EmptyTypes);
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -2909,6 +3246,8 @@ namespace MonoTests.System.Reflection.Emit
                                        new ParameterModifier [0]);
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -2930,6 +3269,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.GetConstructors ();
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -3225,6 +3566,8 @@ namespace MonoTests.System.Reflection.Emit
                                        BindingFlags.Instance);
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -3232,11 +3575,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetCustomAttributesIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetCustomAttributes (false);
+                       try {
+                               tb.GetCustomAttributes (false);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -3257,11 +3608,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetCustomAttributesOfTypeIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetCustomAttributes (typeof (ObsoleteAttribute), false);
+                       try {
+                               tb.GetCustomAttributes (typeof (ObsoleteAttribute), false);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -3283,21 +3642,35 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (ArgumentNullException))]
                public void TestGetCustomAttributesOfNullTypeComplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        tb.CreateType ();
-                       tb.GetCustomAttributes (null, false);
+                       try {
+                               tb.GetCustomAttributes (null, false);
+                               Assert.Fail ("#1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("attributeType", ex.ParamName, "#5");
+                       }
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                [Ignore ("mcs depends on this")]
                public void TestGetEventsIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetEvents ();
+                       try {
+                               tb.GetEvents ();
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               throw;
+                       }
                }
 
                [Test]
@@ -3322,12 +3695,19 @@ namespace MonoTests.System.Reflection.Emit
 
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                [Ignore ("mcs depends on this")]
                public void TestGetEventsFlagsIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetEvents (BindingFlags.Public);
+                       try {
+                               tb.GetEvents (BindingFlags.Public);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               throw;
+                       }
                }
 
                [Test]
@@ -3553,12 +3933,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                [Ignore ("mcs depends on this")]
                public void TestGetEventIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetEvent ("FOO");
+                       try {
+                               tb.GetEvent ("FOO");
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               throw;
+                       }
                }
 
                [Test]
@@ -3583,12 +3970,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                [Ignore ("mcs depends on this")]
                public void TestGetEventFlagsIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetEvent ("FOO", BindingFlags.Public);
+                       try {
+                               tb.GetEvent ("FOO", BindingFlags.Public);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               throw;
+                       }
                }
 
                [Test]
@@ -4322,6 +4716,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.GetFields (BindingFlags.Instance | BindingFlags.Public);
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -4579,6 +4975,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.GetField ("test");
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -4652,6 +5050,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.GetField ("test", BindingFlags.Public);
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -5630,11 +6030,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetPropertyIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetProperty ("test");
+                       try {
+                               tb.GetProperty ("test");
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -5652,6 +6060,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.GetProperty ("CustomerName");
                                Assert.Fail ("#1");
                        } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
                                Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
                                Assert.IsNull (ex.InnerException, "#3");
                                Assert.IsNotNull (ex.Message, "#4");
@@ -5659,11 +6069,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetPropertyFlagsIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetProperty ("test", BindingFlags.Public);
+                       try {
+                               tb.GetProperty ("test", BindingFlags.Public);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -6309,24 +6727,24 @@ namespace MonoTests.System.Reflection.Emit
                        TypeBuilder tb = module.DefineType (genTypeName (),
                                TypeAttributes.Abstract);
                        mb = tb.DefineMethod ("Hello", MethodAttributes.Public,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Run", MethodAttributes.Private,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Execute", MethodAttributes.Public |
                                MethodAttributes.Static,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Init", MethodAttributes.Public |
                                MethodAttributes.Abstract | MethodAttributes.Virtual,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
 
                        MethodInfo [] methods = tb.GetMethods ();
                        Assert.AreEqual (7, methods.Length, "#A");
@@ -6370,24 +6788,24 @@ namespace MonoTests.System.Reflection.Emit
                        TypeBuilder tb = module.DefineType (genTypeName (),
                                TypeAttributes.Abstract);
                        mb = tb.DefineMethod ("Hello", MethodAttributes.Public,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Run", MethodAttributes.Private,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Execute", MethodAttributes.Public |
                                MethodAttributes.Static,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Init", MethodAttributes.Public |
                                MethodAttributes.Abstract | MethodAttributes.Virtual,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
 
                        try {
                                tb.GetMethods ();
@@ -6409,7 +6827,7 @@ namespace MonoTests.System.Reflection.Emit
                        TypeBuilder tb = module.DefineType (genTypeName (),
                                TypeAttributes.Abstract);
                        mb = tb.DefineMethod ("Hello", MethodAttributes.Public,
-                               typeof (string), new Type [0]);
+                               typeof (string), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ldstr, "Hi! ");
                        ilgen.Emit (OpCodes.Ldarg_1);
@@ -6419,19 +6837,19 @@ namespace MonoTests.System.Reflection.Emit
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Run", MethodAttributes.Private,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Execute", MethodAttributes.Public |
                                MethodAttributes.Static,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Init", MethodAttributes.Public |
                                MethodAttributes.Abstract | MethodAttributes.Virtual,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
 
                        Type emittedType = tb.CreateType ();
 
@@ -7108,24 +7526,24 @@ namespace MonoTests.System.Reflection.Emit
                        TypeBuilder tb = module.DefineType (genTypeName (),
                                TypeAttributes.Abstract);
                        mb = tb.DefineMethod ("Hello", MethodAttributes.Public,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Run", MethodAttributes.Private,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Execute", MethodAttributes.Public |
                                MethodAttributes.Static,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Init", MethodAttributes.Public |
                                MethodAttributes.Abstract | MethodAttributes.Virtual,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
 
                        methods = tb.GetMethods (BindingFlags.Public |
                                BindingFlags.Instance);
@@ -7169,24 +7587,24 @@ namespace MonoTests.System.Reflection.Emit
                        TypeBuilder tb = module.DefineType (genTypeName (),
                                TypeAttributes.Abstract);
                        mb = tb.DefineMethod ("Hello", MethodAttributes.Public,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Run", MethodAttributes.Private,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Execute", MethodAttributes.Public |
                                MethodAttributes.Static,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
                        ilgen = mb.GetILGenerator ();
                        ilgen.Emit (OpCodes.Ret);
 
                        mb = tb.DefineMethod ("Init", MethodAttributes.Public |
                                MethodAttributes.Abstract | MethodAttributes.Virtual,
-                               typeof (void), new Type [0]);
+                               typeof (void), Type.EmptyTypes);
 
                        try {
                                tb.GetMethods (BindingFlags.Public | BindingFlags.Instance);
@@ -7203,7 +7621,7 @@ namespace MonoTests.System.Reflection.Emit
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        MethodBuilder helloMethod = tb.DefineMethod ("HelloMethod",
-                               MethodAttributes.Public, typeof (string), new Type [0]);
+                               MethodAttributes.Public, typeof (string), Type.EmptyTypes);
                        ILGenerator helloMethodIL = helloMethod.GetILGenerator ();
                        helloMethodIL.Emit (OpCodes.Ldstr, "Hi! ");
                        helloMethodIL.Emit (OpCodes.Ldarg_1);
@@ -7848,11 +8266,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetMemberIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetMember ("FOO", MemberTypes.All, BindingFlags.Public);
+                       try {
+                               tb.GetMember ("FOO", MemberTypes.All, BindingFlags.Public);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -7868,11 +8294,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetMembersIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetMembers ();
+                       try {
+                               tb.GetMembers ();
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -7885,11 +8319,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetMembersFlagsIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetMembers (BindingFlags.Public);
+                       try {
+                               tb.GetMembers (BindingFlags.Public);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -7908,11 +8350,19 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (NotSupportedException))]
                public void TestGetInterfaceIncomplete ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
-                       tb.GetInterface ("FOO", true);
+                       try {
+                               tb.GetInterface ("FOO", true);
+                               Assert.Fail ("#1");
+                       } catch (NotSupportedException ex) {
+                               // The invoked member is not supported in a
+                               // dynamic module
+                               Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -7931,23 +8381,37 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void TestAddDeclarativeSecurityAlreadyCreated ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        tb.CreateType ();
 
                        PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
-                       tb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+                       try {
+                               tb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Unable to change after type has been created
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
-               [ExpectedException (typeof (ArgumentNullException))]
                public void TestAddDeclarativeSecurityNullPermissionSet ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
+                       try {
+                               tb.AddDeclarativeSecurity (SecurityAction.Demand, null);
+                               Assert.Fail ("#1");
+                       } catch (ArgumentNullException ex) {
+                               Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.AreEqual ("pset", ex.ParamName, "#5");
+                       }
 
-                       tb.AddDeclarativeSecurity (SecurityAction.Demand, null);
                }
 
                [Test]
@@ -7971,14 +8435,22 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void TestAddDeclarativeSecurityDuplicateAction ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
 
                        PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
                        tb.AddDeclarativeSecurity (SecurityAction.Demand, set);
-                       tb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+                       try {
+                               tb.AddDeclarativeSecurity (SecurityAction.Demand, set);
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Multiple permission sets specified with the
+                               // same SecurityAction
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -7987,7 +8459,7 @@ namespace MonoTests.System.Reflection.Emit
                        TypeAttributes typeAttrs = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
                        TypeBuilder enumToCreate = module.DefineType (genTypeName (), typeAttrs,
                                                                                                                 typeof (Enum));
-                       enumToCreate.SetCustomAttribute (new CustomAttributeBuilder (typeof (FlagsAttribute).GetConstructors () [0], new Type [0]));
+                       enumToCreate.SetCustomAttribute (new CustomAttributeBuilder (typeof (FlagsAttribute).GetConstructors () [0], Type.EmptyTypes));
                        // add value__ field, see DefineEnum method of ModuleBuilder
                        enumToCreate.DefineField ("value__", typeof (Int32),
                                FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
@@ -8059,7 +8531,7 @@ namespace MonoTests.System.Reflection.Emit
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
                        ConstructorInfo attrCtor = typeof (SuppressUnmanagedCodeSecurityAttribute).
-                               GetConstructor (new Type [0]);
+                               GetConstructor (Type.EmptyTypes);
                        CustomAttributeBuilder caBuilder = new CustomAttributeBuilder (
                                attrCtor, new object [0]);
                        Assert.IsTrue ((tb.Attributes & TypeAttributes.HasSecurity) == 0, "#1");
@@ -8178,23 +8650,35 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void EmptyMethodBody ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
 
                        tb.DefineMethod ("foo", MethodAttributes.Public, typeof (void), new Type [] { });
-                       tb.CreateType ();
+                       try {
+                               tb.CreateType ();
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void EmptyCtorBody ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
 
                        tb.DefineConstructor (0, CallingConventions.Standard, null);
-                       tb.CreateType ();
+                       try {
+                               tb.CreateType ();
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -8245,11 +8729,17 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
                public void Fail_MakeGenericType ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
-                       tb.MakeGenericType (typeof (int));
+                       try {
+                               tb.MakeGenericType (typeof (int));
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                       }
                }
 
                [Test]
@@ -8387,10 +8877,30 @@ namespace MonoTests.System.Reflection.Emit
                }
 #endif
 
-               public interface IDelegateFactory {
+               public interface IDelegateFactory
+               {
                        Delegate Create (Delegate del);
                }
 
+               [Test]
+               public void CreateType_Ctor_NoBody ()
+               {
+                       TypeBuilder tb = module.DefineType (genTypeName ());
+                       tb.DefineConstructor (MethodAttributes.Public,
+                               CallingConventions.Standard,
+                               new Type [] { typeof (string) });
+                       try {
+                               tb.CreateType ();
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException ex) {
+                               // Method '.ctor' does not have a method body
+                               Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2");
+                               Assert.IsNull (ex.InnerException, "#3");
+                               Assert.IsNotNull (ex.Message, "#4");
+                               Assert.IsTrue (ex.Message.IndexOf (".ctor") != -1, "#5");
+                       }
+               }
+
                [Test] //bug #361689
                public void CreateTypeFailsWithInvalidMethodOverride ()
                {
@@ -8409,7 +8919,6 @@ namespace MonoTests.System.Reflection.Emit
                        }
                }
 
-
                static MethodInfo GetMethodByName (MethodInfo [] methods, string name)
                {
                        foreach (MethodInfo mi in methods)
index 32728889bd5413866c1486ca68af22657130ce4e..7861565ee3e5b041381bc4aebcb5a14860f5c3fa 100644 (file)
@@ -127,6 +127,7 @@ System.Reflection/TypeDelegatorTest.cs
 System.Reflection.Emit/AssemblyBuilderTest.cs
 System.Reflection.Emit/AssemblyBuilderAccessTest.cs
 System.Reflection.Emit/ConstructorBuilderTest.cs
+System.Reflection.Emit/ConstructorOnTypeBuilderInstTest.cs
 System.Reflection.Emit/CustomAttributeBuilderTest.cs
 System.Reflection.Emit/DynamicMethodTest.cs
 System.Reflection.Emit/EnumBuilderTest.cs
diff --git a/mcs/errors/gcs0831-2.cs b/mcs/errors/gcs0831-2.cs
new file mode 100644 (file)
index 0000000..ed0f351
--- /dev/null
@@ -0,0 +1,22 @@
+// CS0831:  An expression tree may not contain a base access
+// Line: 14
+
+using System;
+using System.Linq.Expressions;
+
+class B
+{
+       protected bool Core {
+               get {
+                       return true;
+               }
+       }
+}
+
+class C : B
+{
+       public void Test ()
+       {
+               Expression<Func<bool>> e = () => base.Core;
+       }
+}
diff --git a/mcs/errors/gcs0831-3.cs b/mcs/errors/gcs0831-3.cs
new file mode 100644 (file)
index 0000000..171ce9c
--- /dev/null
@@ -0,0 +1,22 @@
+// CS0831: An expression tree may not contain a base access
+// Line: 20
+
+using System;
+using System.Linq.Expressions;
+
+class B
+{
+       protected B this [int i] {
+               get {
+                       return null;
+               }
+       }
+}
+
+class C : B
+{
+       public void Test ()
+       {
+               Expression<Func<B>> e = () => base [8];
+       }
+}
diff --git a/mcs/errors/gcs0831.cs b/mcs/errors/gcs0831.cs
new file mode 100644 (file)
index 0000000..2dbb547
--- /dev/null
@@ -0,0 +1,21 @@
+// CS0831: An expression tree may not contain a base access
+// Line: 14
+
+using System;
+using System.Linq.Expressions;
+
+class B
+{
+       protected int Core ()
+       {
+               return 4;
+       }
+}
+
+class C : B
+{
+       public void Test ()
+       {
+               Expression<Func<int>> e = () => base.Core ();
+       }
+}
diff --git a/mcs/errors/gcs0832-4.cs b/mcs/errors/gcs0832-4.cs
new file mode 100644 (file)
index 0000000..cf0f6ae
--- /dev/null
@@ -0,0 +1,25 @@
+// CS0832: An expression tree cannot contain an assignment operator
+// Line: 19
+
+using System;
+using System.Linq.Expressions;
+
+public delegate void EventHandler (int i, int j);
+
+public class Button
+{
+       public event EventHandler Click;
+}
+
+public class Blah
+{
+       public static void Main ()
+       {
+               Button b = new Button ();
+               Expression<Action> e = () => b.Click += new EventHandler (Button1_Click);
+       }
+
+       public static void Button1_Click (int i, int j)
+       {
+       }
+}
diff --git a/mcs/errors/gcs0843.cs b/mcs/errors/gcs0843.cs
new file mode 100644 (file)
index 0000000..35621cd
--- /dev/null
@@ -0,0 +1,13 @@
+// CS0843: An automatically implemented property `S.Short' must be fully assigned before control leaves the constructor. Consider calling default contructor
+// Line: 8
+
+using System;
+
+struct S
+{
+       public S (int value)
+       {
+       }
+       
+       public short Short { get; set; }
+}
diff --git a/mcs/errors/gcs0845.cs b/mcs/errors/gcs0845.cs
new file mode 100644 (file)
index 0000000..47cba43
--- /dev/null
@@ -0,0 +1,13 @@
+// CS0845: An expression tree cannot contain a coalescing operator with null left side
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       public static void Main ()
+       {
+               Expression<Func<bool?, bool?>> e = (a) => null ?? a;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/gcs1944-2.cs b/mcs/errors/gcs1944-2.cs
new file mode 100644 (file)
index 0000000..5280413
--- /dev/null
@@ -0,0 +1,18 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 15
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       unsafe delegate int* D (int i);
+       
+       public static void Main ()
+       {
+               unsafe {
+                       Expression<D> e = (int p) => &p;
+               }
+       }
+}
diff --git a/mcs/errors/gcs1944-3.cs b/mcs/errors/gcs1944-3.cs
new file mode 100644 (file)
index 0000000..3a5e310
--- /dev/null
@@ -0,0 +1,18 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 15
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       unsafe delegate int D (int* i);
+       
+       public static void Main ()
+       {
+               unsafe {
+                       Expression<D> e = p => *p;
+               }
+       }
+}
diff --git a/mcs/errors/gcs1944-4.cs b/mcs/errors/gcs1944-4.cs
new file mode 100644 (file)
index 0000000..33fc4d6
--- /dev/null
@@ -0,0 +1,18 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 15
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       unsafe delegate int* D (int* i);
+       
+       public static void Main ()
+       {
+               unsafe {
+                       Expression<D> e = p => p + 1;
+               }
+       }
+}
diff --git a/mcs/errors/gcs1944-5.cs b/mcs/errors/gcs1944-5.cs
new file mode 100644 (file)
index 0000000..b53a1ba
--- /dev/null
@@ -0,0 +1,16 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 13
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       public static void Main ()
+       {
+               unsafe {
+                       Expression<Func<int>> e = () => sizeof (long*);
+               }
+       }
+}
diff --git a/mcs/errors/gcs1944-6.cs b/mcs/errors/gcs1944-6.cs
new file mode 100644 (file)
index 0000000..60efab1
--- /dev/null
@@ -0,0 +1,17 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 14
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       unsafe delegate byte* D (int*[] d);
+       public static void Main ()
+       {
+               unsafe {
+                       Expression<D> e6 = (p) => (byte*)p [10];
+               }
+       }
+}
diff --git a/mcs/errors/gcs1944-7.cs b/mcs/errors/gcs1944-7.cs
new file mode 100644 (file)
index 0000000..f9ff69c
--- /dev/null
@@ -0,0 +1,18 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 15
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       unsafe delegate int* D ();
+       
+       public static void Main ()
+       {
+               unsafe {
+                       Expression<D> e = () => default (int*);
+               }
+       }
+}
diff --git a/mcs/errors/gcs1944.cs b/mcs/errors/gcs1944.cs
new file mode 100644 (file)
index 0000000..5b5668a
--- /dev/null
@@ -0,0 +1,17 @@
+// CS1944: An expression tree cannot contain an unsafe pointer operation
+// Line: 14
+// Compiler options: -unsafe
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       public static void Main ()
+       {
+               unsafe {
+                       int*[] p = null;
+                       Expression<Func<int>> e6 = () => (int)p [10];
+               }
+       }
+}
diff --git a/mcs/errors/gcs1945.cs b/mcs/errors/gcs1945.cs
new file mode 100644 (file)
index 0000000..1f70335
--- /dev/null
@@ -0,0 +1,13 @@
+// CS1945: An expression tree cannot contain an anonymous method expression
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       public static void Main ()
+       {
+               Expression<Func<Func<int>>> e = () => delegate () { return 1; };                
+       }
+}
diff --git a/mcs/errors/gcs1953.cs b/mcs/errors/gcs1953.cs
new file mode 100644 (file)
index 0000000..ba5dbad
--- /dev/null
@@ -0,0 +1,13 @@
+// CS1953: An expression tree cannot contain an expression with method group
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+       public static void Main ()
+       {
+               Expression<Func<bool>> e = () => "1".ToString is string;
+       }
+}
\ No newline at end of file
index 17f9a941b8673aaa08eeb2cec9033edfee8239e0..abb6b39b695919371005b22edd4715076e1e93d1 100644 (file)
@@ -1,3 +1,52 @@
+2008-05-01  Marek Safar  <marek.safar@gmail.com>
+
+       * constant.cs, literal.cs: IsLiteral property for error reporting.
+       
+       * ecore.cs, expression.cs: Implemented Property expression.
+
+2008-05-01  Marek Safar  <marek.safar@gmail.com>
+
+       * class.cs, modifiers.cs, flowanalysis.cs: New BACKING_FIELD flag.
+       
+       * nullable.cs: Implemented nullable coalescing null operator.
+
+       * ecore.cs, expression.cs: Expression trees work.
+
+2008-05-01  Marek Safar  <marek.safar@gmail.com>
+
+       * ecore.cs: CreateExpressionTree is finally abstract.
+
+       * expression.cs, linq.cs: Updated.
+
+2008-05-01  Marek Safar  <marek.safar@gmail.com>
+
+       * expression.cs, ecore.cs: Block base access expression inside expression
+       tree.
+
+2008-05-01  Marek Safar  <marek.safar@gmail.com>
+
+       A fix for bug #385058
+       * expression.cs: User-defined operator implementations always take
+       precedence over predefined operator implementations.
+
+2008-04-30  Marek Safar  <marek.safar@gmail.com>
+
+       * assign.cs, anonymous.cs, lambda.cs, nullable.cs, ecore.cs, linq.cs,
+       class.cs, iterators.cs, expression.cs, attribute.cs: Filled a few more
+       expression tree conversions.
+       
+2008-04-30  Marek Safar  <marek.safar@gmail.com>
+
+       * typemanager.cs, ecore.cs, class.cs, expression.cs, doc.cs: Merged all
+       operators method details to Operator class.
+
+2008-04-30  Marek Safar  <marek.safar@gmail.com>
+
+       * anonymous.cs: Pass unsafe flags to anonymous container.
+       
+       * ecore.cs, expression.cs, statement.cs: Block unsafe pointer operations
+       inside expression tree.
+
 2008-04-29  Martin Baulig  <martin@ximian.com>
 
        * cs-tokenizer.cs (Tokenizer.Position): Added `line'.
index 9ed6650ce8da48b5edc5d2ecfa1039279004433f..794956f53e7501e4c51d5a24e5c6e0b144646fbc 100644 (file)
@@ -646,6 +646,11 @@ namespace Mono.CSharp {
                                get { return scope; }
                        }
 
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               throw new NotSupportedException ("ET");
+                       }
+
                        public override Expression DoResolve (EmitContext ec)
                        {
                                if (scope_ctor != null)
@@ -1423,6 +1428,11 @@ namespace Mono.CSharp {
                }
 
                protected virtual Expression CreateExpressionTree (EmitContext ec, Type delegate_type)
+               {
+                       return CreateExpressionTree (ec);
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
                {
                        Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree");
                        return null;
@@ -1643,6 +1653,9 @@ namespace Mono.CSharp {
                        
                        if (ec.IsInFieldInitializer)
                                flags |= EmitContext.Flags.InFieldInitializer;
+
+                       if (ec.IsInUnsafeScope)
+                               flags |= EmitContext.Flags.InUnsafe;
                        
                        // HACK: Flag with 0 cannot be set 
                        if (flags != 0)
@@ -1791,6 +1804,12 @@ namespace Mono.CSharp {
                        return TypeManager.CSharpName (DelegateType);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression");
+                       return null;
+               }
+
                //
                // Creates the host for the anonymous method
                //
@@ -1938,6 +1957,11 @@ namespace Mono.CSharp {
                        this.am = am;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return am.CreateExpressionTree (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Value;
index 03350c7021aae2ff1145d393ee57c7b6f39ea499..8ae6cd57bbbb9b6b0dfbabe6b26ac8e3a39590de 100644 (file)
@@ -206,6 +206,11 @@ namespace Mono.CSharp {
                        builder = null;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        return this;
@@ -476,6 +481,11 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return new SimpleAssign (target, source).CreateExpressionTree (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Value;
@@ -524,6 +534,7 @@ namespace Mono.CSharp {
                        this.op = op;
                }
 
+               // !!! What a stupid name
                public class Helper : Expression {
                        Expression child;
                        public Helper (Expression child)
@@ -532,6 +543,11 @@ namespace Mono.CSharp {
                                this.loc = child.Location;
                        }
 
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               throw new NotSupportedException ("ET");
+                       }
+
                        public override Expression DoResolve (EmitContext ec)
                        {
                                child = child.Resolve (ec);
index 099055b733cf2d9182b0e6b06b950edd402d3c5a..098134db35fbeac592de457063cba626c871eabc 100644 (file)
@@ -1272,6 +1272,11 @@ namespace Mono.CSharp {
                        return e.TypeArgument;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        throw new NotImplementedException ();
index ffb5d3d242d3015b23b767098ab22038cc655336..8b19e702a80c348fa3a2097ba7a08abb5d622931 100644 (file)
@@ -4554,6 +4554,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
                {
                        if (argument_list != null){
@@ -6027,6 +6032,17 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public override string GetSignatureForError ()
+               {
+                       string s = base.GetSignatureForError ();
+                       if ((ModFlags & Modifiers.BACKING_FIELD) == 0)
+                               return s;
+
+                       // Undecorate name mangling
+                       int l = s.LastIndexOf ('>');
+                       return s.Substring (0, l).Remove (s.LastIndexOf ('<'), 1);
+               }
+
                protected override bool VerifyClsCompliance ()
                {
                        if (!base.VerifyClsCompliance ())
@@ -6848,7 +6864,7 @@ namespace Mono.CSharp {
                        // Make the field
                        Field field = new Field (
                                Parent, type_name,
-                               Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
+                               Modifiers.BACKING_FIELD | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
                            "<" + Name + ">k__BackingField", null, Location);
                        ((TypeContainer)Parent).AddField (field);
 
@@ -7873,6 +7889,39 @@ namespace Mono.CSharp {
                };
 
                public readonly OpType OperatorType;
+
+               static readonly string [] [] names;
+
+               static Operator ()
+               {
+                       names = new string[(int)OpType.TOP][];
+                       names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
+                       names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
+                       names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
+                       names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
+                       names [(int) OpType.True] = new string [] { "true", "op_True" };
+                       names [(int) OpType.False] = new string [] { "false", "op_False" };
+                       names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
+                       names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
+                       names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
+                       names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
+                       names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
+                       names [(int) OpType.Division] = new string [] { "/", "op_Division" };
+                       names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
+                       names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
+                       names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
+                       names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
+                       names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
+                       names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
+                       names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
+                       names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
+                       names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
+                       names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
+                       names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
+                       names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
+                       names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
+                       names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
+               }
                
                public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
                                 int mod_flags, Parameters parameters,
@@ -7907,9 +7956,9 @@ namespace Mono.CSharp {
 
                        // imlicit and explicit operator of same types are not allowed
                        if (OperatorType == OpType.Explicit)
-                               Parent.MemberCache.CheckExistingMembersOverloads (this, "op_Implicit", Parameters);
+                               Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters);
                        else if (OperatorType == OpType.Implicit)
-                               Parent.MemberCache.CheckExistingMembersOverloads (this, "op_Explicit", Parameters);
+                               Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters);
 
                        if (MemberType == TypeManager.void_type) {
                                Report.Error (590, Location, "User-defined operators cannot return void");
@@ -8072,61 +8121,30 @@ namespace Mono.CSharp {
 
                public static string GetName (OpType ot)
                {
-                       switch (ot){
-                       case OpType.LogicalNot:
-                               return "!";
-                       case OpType.OnesComplement:
-                               return "~";
-                       case OpType.Increment:
-                               return "++";
-                       case OpType.Decrement:
-                               return "--";
-                       case OpType.True:
-                               return "true";
-                       case OpType.False:
-                               return "false";
-                       case OpType.Addition:
-                               return "+";
-                       case OpType.Subtraction:
-                               return "-";
-                       case OpType.UnaryPlus:
-                               return "+";
-                       case OpType.UnaryNegation:
-                               return "-";
-                       case OpType.Multiply:
-                               return "*";
-                       case OpType.Division:
-                               return "/";
-                       case OpType.Modulus:
-                               return "%";
-                       case OpType.BitwiseAnd:
-                               return "&";
-                       case OpType.BitwiseOr:
-                               return "|";
-                       case OpType.ExclusiveOr:
-                               return "^";
-                       case OpType.LeftShift:
-                               return "<<";
-                       case OpType.RightShift:
-                               return ">>";
-                       case OpType.Equality:
-                               return "==";
-                       case OpType.Inequality:
-                               return "!=";
-                       case OpType.GreaterThan:
-                               return ">";
-                       case OpType.LessThan:
-                               return "<";
-                       case OpType.GreaterThanOrEqual:
-                               return ">=";
-                       case OpType.LessThanOrEqual:
-                               return "<=";
-                       case OpType.Implicit:
-                               return "implicit";
-                       case OpType.Explicit:
-                               return "explicit";
-                       default: return "";
+                       return names [(int) ot] [0];
+               }
+
+               public static string GetName (string metadata_name)
+               {
+                       for (int i = 0; i < names.Length; ++i) {
+                               if (names [i] [1] == metadata_name)
+                                       return names [i] [0];
                        }
+                       return null;
+               }
+
+               public static string GetMetadataName (OpType ot)
+               {
+                       return names [(int) ot] [1];
+               }
+
+               public static string GetMetadataName (string name)
+               {
+                       for (int i = 0; i < names.Length; ++i) {
+                               if (names [i] [0] == name)
+                                       return names [i] [1];
+                       }
+                       return null;
                }
 
                public OpType GetMatchingOperator ()
@@ -8153,22 +8171,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public static OpType GetOperatorType (string name)
-               {
-                       if (name.StartsWith ("op_")){
-                               for (int i = 0; i < Unary.oper_names.Length; ++i) {
-                                       if (Unary.oper_names [i] == name)
-                                               return (OpType)i;
-                               }
-
-                               for (int i = 0; i < Binary.oper_names.Length; ++i) {
-                                       if (Binary.oper_names [i] == name)
-                                               return (OpType)i;
-                               }
-                       }
-                       return OpType.TOP;
-               }
-
                public override string GetSignatureForError ()
                {
                        StringBuilder sb = new StringBuilder ();
index 2b25942e9ade800cb9f6bb4c098665364699b816..93b97365f5039d85c759dde1fe3e106aafb4197d 100644 (file)
@@ -76,6 +76,16 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
+               {
+                       if (!expl && IsLiteral && type != TypeManager.string_type) {
+                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
+                                       GetValue ().ToString (), TypeManager.CSharpName (target));
+                       } else {
+                               base.Error_ValueCannotBeConverted (ec, loc, target, expl);
+                       }
+               }
+
                public Constant ImplicitConversionRequired (Type type, Location loc)
                {
                        Constant c = ConvertImplicitly (type);
@@ -220,6 +230,13 @@ namespace Mono.CSharp {
                        get;
                }
 
+               //
+               // When constant is declared as literal
+               //
+               public virtual bool IsLiteral {
+                       get { return false; }
+               }
+
                //
                // Returns true iff 1) the stack type of this is one of Object, 
                // int32, int64 and 2) this == 0 or this == null.
index faed45f4903dadd47570c4438f9e629b924ce57c..efe1e701c725f5f26ba492f811cd4518b56612ad 100644 (file)
@@ -505,11 +505,11 @@ namespace Mono.CSharp {
                        string oper = null;
                        string return_type_name = null;
                        if (member_name.StartsWith ("implicit operator ")) {
-                               oper = "op_Implicit";
+                               Operator.GetMetadataName (Operator.OpType.Implicit);
                                return_type_name = member_name.Substring (18).Trim (wsChars);
                        }
                        else if (member_name.StartsWith ("explicit operator ")) {
-                               oper = "op_Explicit";
+                               oper = Operator.GetMetadataName (Operator.OpType.Explicit);
                                return_type_name = member_name.Substring (18).Trim (wsChars);
                        }
                        else if (member_name.StartsWith ("operator ")) {
@@ -518,58 +518,19 @@ namespace Mono.CSharp {
                                // either unary or binary
                                case "+":
                                        oper = param_list.Length == 2 ?
-                                               Binary.GetOperatorMetadataName (Binary.Operator.Addition) :
-                                               Unary.oper_names [(int) Unary.Operator.UnaryPlus];
+                                               Operator.GetMetadataName (Operator.OpType.Addition) :
+                                               Operator.GetMetadataName (Operator.OpType.UnaryPlus);
                                        break;
                                case "-":
                                        oper = param_list.Length == 2 ?
-                                               Binary.GetOperatorMetadataName (Binary.Operator.Subtraction) :
-                                               Unary.oper_names [(int) Unary.Operator.UnaryNegation];
+                                               Operator.GetMetadataName (Operator.OpType.Subtraction) :
+                                               Operator.GetMetadataName (Operator.OpType.UnaryNegation);
                                        break;
-                               // unary
-                               case "!":
-                                       oper = Unary.oper_names [(int) Unary.Operator.LogicalNot]; break;
-                               case "~":
-                                       oper = Unary.oper_names [(int) Unary.Operator.OnesComplement]; break;
-                                       
-                               case "++":
-                                       oper = "op_Increment"; break;
-                               case "--":
-                                       oper = "op_Decrement"; break;
-                               case "true":
-                                       oper = "op_True"; break;
-                               case "false":
-                                       oper = "op_False"; break;
-                               // binary
-                               case "*":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.Multiply); break;
-                               case "/":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.Division); break;
-                               case "%":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.Modulus); break;
-                               case "&":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.BitwiseAnd); break;
-                               case "|":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.BitwiseOr); break;
-                               case "^":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.ExclusiveOr); break;
-                               case "<<":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.LeftShift); break;
-                               case ">>":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.RightShift); break;
-                               case "==":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.Equality); break;
-                               case "!=":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.Inequality); break;
-                               case "<":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.LessThan); break;
-                               case ">":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.GreaterThan); break;
-                               case "<=":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.LessThanOrEqual); break;
-                               case ">=":
-                                       oper = Binary.GetOperatorMetadataName (Binary.Operator.GreaterThanOrEqual); break;
                                default:
+                                       oper = Operator.GetMetadataName (oper);
+                                       if (oper != null)
+                                               break;
+
                                        warning_type = 1584;
                                        Report.Warning (1020, 1, mc.Location, "Overloadable {0} operator is expected", param_list.Length == 2 ? "binary" : "unary");
                                        Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
index ffa591edb434e472bc5d31962ce2dcdaeb6d4331..f2d06c506a3566592fe31fd855360102d6ca27b4 100644 (file)
@@ -393,12 +393,6 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) {
-                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
-                                       ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target));
-                               return;
-                       }
-
                        Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
                                TypeManager.CSharpName (type),
                                TypeManager.CSharpName (target));
@@ -914,6 +908,11 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
                }
 
+               protected void Error_PointerInsideExpressionTree ()
+               {
+                       Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
+               }
+
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -935,7 +934,8 @@ namespace Mono.CSharp {
                static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
                        MethodGroupExpr operator_group;
-                       operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
+                       string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
+                       operator_group = MethodLookup (ec.ContainerType, e.Type, mname, loc) as MethodGroupExpr;
                        if (operator_group == null)
                                return null;
 
@@ -1251,11 +1251,10 @@ namespace Mono.CSharp {
                        return cloned;
                }
 
-               public virtual Expression CreateExpressionTree (EmitContext ec)
-               {
-                       throw new NotImplementedException (
-                               "Expression tree conversion not implemented for " + GetType ());
-               }
+               //
+               // Implementation of expression to expression tree conversion
+               //
+               public abstract Expression CreateExpressionTree (EmitContext ec);
 
                protected Expression CreateExpressionFactoryCall (string name, ArrayList args)
                {
@@ -1352,6 +1351,10 @@ namespace Mono.CSharp {
                        ArrayList args = new ArrayList (2);
                        args.Add (new Argument (child.CreateExpressionTree (ec)));
                        args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+
+                       if (type.IsPointer || child.Type.IsPointer)
+                               Error_PointerInsideExpressionTree ();
+
                        return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args);
                }
 
@@ -1601,6 +1604,9 @@ namespace Mono.CSharp {
                        ArrayList args = new ArrayList (2);
                        args.Add (new Argument (child.CreateExpressionTree (ec)));
                        args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       if (type.IsPointer)
+                               Error_PointerInsideExpressionTree ();
+
                        return CreateExpressionFactoryCall ("Convert", args);
                }
 
@@ -2751,6 +2757,12 @@ namespace Mono.CSharp {
        ///   section 10.8.1 (Fully Qualified Names).
        /// </summary>
        public abstract class FullNamedExpression : Expression {
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
                        return this;
@@ -3098,6 +3110,11 @@ namespace Mono.CSharp {
                                      "with an instance reference, qualify it with a type name instead", name);
                }
 
+               public static void Error_BaseAccessInExpressionTree (Location loc)
+               {
+                       Report.Error (831, loc, "An expression tree may not contain a base access");
+               }
+
                // TODO: possible optimalization
                // Cache resolved constant result in FieldBuilder <-> expression map
                public virtual MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
@@ -3616,8 +3633,18 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
+                       if (best_candidate == null) {
+                               Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
+                               return null;
+                       }
+
                        if (best_candidate.IsConstructor)
                                return new TypeOfConstructorInfo (best_candidate, loc);
+
+                       IMethodData md = TypeManager.GetMethod (best_candidate);
+                       if (md != null && md.IsExcluded ())
+                               Report.Error (765, loc,
+                                       "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
                        
                        return new TypeOfMethodInfo (best_candidate, loc);
                }
@@ -4522,7 +4549,7 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       throw new NotSupportedException ();
+                       throw new NotSupportedException ("ET");
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -5070,18 +5097,25 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
+                       ArrayList args;
                        if (IsSingleDimensionalArrayLength ()) {
-                               ArrayList args = new ArrayList (1);
+                               args = new ArrayList (1);
                                args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
                                return CreateExpressionFactoryCall ("ArrayLength", args);
                        }
 
-                       // TODO: it's waiting for PropertyExpr refactoring
-                       //ArrayList args = new ArrayList (2);
-                       //args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
-                       //args.Add (getter expression);
-                       //return CreateExpressionFactoryCall ("Property", args);
-                       return base.CreateExpressionTree (ec);
+                       if (is_base) {
+                               Error_BaseAccessInExpressionTree (loc);
+                               return null;
+                       }
+
+                       args = new ArrayList (2);
+                       if (InstanceExpression == null)
+                               args.Add (new Argument (new NullLiteral (loc)));
+                       else
+                               args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOfMethodInfo (getter, loc)));
+                       return CreateExpressionFactoryCall ("Property", args);
                }
 
                public Expression CreateSetterTypeOfExpression ()
@@ -5566,7 +5600,7 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       throw new NotSupportedException ();
+                       throw new NotSupportedException ("ET");
                }
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
@@ -5633,6 +5667,11 @@ namespace Mono.CSharp {
                        this.loc = loc;
                        eclass = ExprClass.Value;
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
index 4c1b276c5059ab7a8dca5dac0375d977d6cd8633..d3fb27ac6d31382ed7367f69848be1a80d686124 100644 (file)
@@ -101,6 +101,12 @@ namespace Mono.CSharp {
                public ParenthesizedExpression (Expression expr)
                {
                        this.Expr = expr;
+                       this.loc = expr.Location;
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -114,13 +120,6 @@ namespace Mono.CSharp {
                        throw new Exception ("Should not happen");
                }
 
-               public override Location Location
-               {
-                       get {
-                               return Expr.Location;
-                       }
-               }
-
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        ParenthesizedExpression target = (ParenthesizedExpression) t;
@@ -138,7 +137,6 @@ namespace Mono.CSharp {
                        AddressOf,  TOP
                }
 
-               public static readonly string [] oper_names;
                static Type [] [] predefined_operators;
 
                public readonly Operator Oper;
@@ -152,17 +150,6 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
-               static Unary ()
-               {
-                       oper_names = new string [(int)Operator.TOP];
-
-                       oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";
-                       oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
-                       oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
-                       oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
-                       oper_names [(int) Operator.AddressOf] = "op_AddressOf";
-               }
-
                // <summary>
                //   This routine will attempt to simplify the unary expression when the
                //   argument is a constant.
@@ -374,6 +361,9 @@ namespace Mono.CSharp {
                {
                        string method_name;
                        switch (Oper) {
+                       case Operator.AddressOf:
+                               Error_PointerInsideExpressionTree ();
+                               return null;
                        case Operator.UnaryNegation:
                                if (ec.CheckState && user_op == null && !IsFloat (type))
                                        method_name = "NegateChecked";
@@ -673,7 +663,21 @@ namespace Mono.CSharp {
                //
                protected virtual Expression ResolveUserOperator (EmitContext ec, Expression expr)
                {
-                       string op_name = oper_names [(int) Oper];
+                       CSharp.Operator.OpType op_type;
+                       switch (Oper) {
+                       case Operator.LogicalNot:
+                               op_type = CSharp.Operator.OpType.LogicalNot; break;
+                       case Operator.OnesComplement:
+                               op_type = CSharp.Operator.OpType.OnesComplement; break;
+                       case Operator.UnaryNegation:
+                               op_type = CSharp.Operator.OpType.UnaryNegation; break;
+                       case Operator.UnaryPlus:
+                               op_type = CSharp.Operator.OpType.UnaryPlus; break;
+                       default:
+                               throw new InternalErrorException (Oper.ToString ());
+                       }
+
+                       string op_name = CSharp.Operator.GetMetadataName (op_type);
                        MethodGroupExpr user_op = MemberLookup (ec.ContainerType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr;
                        if (user_op == null)
                                return null;
@@ -768,6 +772,12 @@ namespace Mono.CSharp {
                        this.expr = expr;
                        loc = l;
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
                
                public override void Emit (EmitContext ec)
                {
@@ -946,9 +956,9 @@ namespace Mono.CSharp {
                        string op_name;
                        
                        if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
-                               op_name = "op_Increment";
-                       else 
-                               op_name = "op_Decrement";
+                               op_name = Operator.GetMetadataName (Operator.OpType.Increment);
+                       else
+                               op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
 
                        mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
 
@@ -1198,6 +1208,8 @@ namespace Mono.CSharp {
        ///   Implementation of the `is' operator.
        /// </summary>
        public class Is : Probe {
+               Nullable.Unwrap expr_unwrap;
+
                public Is (Expression expr, Expression probe_type, Location l)
                        : base (expr, probe_type, l)
                {
@@ -1214,6 +1226,10 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
+                       if (expr_unwrap != null) {
+                               expr_unwrap.EmitCheck (ec);
+                               return;
+                       }
 
                        expr.Emit (ec);
                        ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
@@ -1224,9 +1240,12 @@ namespace Mono.CSharp {
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        ILGenerator ig = ec.ig;
-
-                       expr.Emit (ec);
-                       ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+                       if (expr_unwrap != null) {
+                               expr_unwrap.EmitCheck (ec);
+                       } else {
+                               expr.Emit (ec);
+                               ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+                       }                       
                        ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
                }
                
@@ -1276,8 +1295,10 @@ namespace Mono.CSharp {
                                        //
                                        // D and T are the same value types but D can be null
                                        //
-                                       if (d_is_nullable && !t_is_nullable)
-                                               return Nullable.HasValue.Create (expr, ec);
+                                       if (d_is_nullable && !t_is_nullable) {
+                                               expr_unwrap = Nullable.Unwrap.Create (expr, ec);
+                                               return this;
+                                       }
                                        
                                        //
                                        // The result is true if D and T are the same value types
@@ -1502,6 +1523,11 @@ namespace Mono.CSharp {
                        get { return expr; }
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        expr = expr.Resolve (ec);
@@ -1591,7 +1617,7 @@ namespace Mono.CSharp {
                        } else {
                                Constant c = New.Constantify (type);
                                if (c != null)
-                                       return new EmptyConstantCast (c, type);
+                                       return c;
 
                                if (!TypeManager.IsValueType (type))
                                        return new EmptyConstantCast (new NullLiteral (Location), type);
@@ -1864,36 +1890,9 @@ namespace Mono.CSharp {
                readonly bool is_compound;
                Expression enum_conversion;
 
-               // This must be kept in sync with Operator!!!
-               public static readonly string [] oper_names;
-
                static PredefinedOperator [] standard_operators;
                static PredefinedOperator [] pointer_operators;
                
-               static Binary ()
-               {
-                       oper_names = new string [18];
-
-                       oper_names [(int) (Operator.Multiply & Operator.ValuesOnlyMask)] = "op_Multiply";
-                       oper_names [(int) (Operator.Division & Operator.ValuesOnlyMask)] = "op_Division";
-                       oper_names [(int) (Operator.Modulus & Operator.ValuesOnlyMask)] = "op_Modulus";
-                       oper_names [(int) (Operator.Addition & Operator.ValuesOnlyMask)] = "op_Addition";
-                       oper_names [(int) (Operator.Subtraction & Operator.ValuesOnlyMask)] = "op_Subtraction";
-                       oper_names [(int) (Operator.LeftShift & Operator.ValuesOnlyMask)] = "op_LeftShift";
-                       oper_names [(int) (Operator.RightShift & Operator.ValuesOnlyMask)] = "op_RightShift";
-                       oper_names [(int) (Operator.LessThan & Operator.ValuesOnlyMask)] = "op_LessThan";
-                       oper_names [(int) (Operator.GreaterThan & Operator.ValuesOnlyMask)] = "op_GreaterThan";
-                       oper_names [(int) (Operator.LessThanOrEqual & Operator.ValuesOnlyMask)] = "op_LessThanOrEqual";
-                       oper_names [(int) (Operator.GreaterThanOrEqual & Operator.ValuesOnlyMask)] = "op_GreaterThanOrEqual";
-                       oper_names [(int) (Operator.Equality & Operator.ValuesOnlyMask)] = "op_Equality";
-                       oper_names [(int) (Operator.Inequality & Operator.ValuesOnlyMask)] = "op_Inequality";
-                       oper_names [(int) (Operator.BitwiseAnd & Operator.ValuesOnlyMask)] = "op_BitwiseAnd";
-                       oper_names [(int) (Operator.BitwiseOr & Operator.ValuesOnlyMask)] = "op_BitwiseOr";
-                       oper_names [(int) (Operator.ExclusiveOr & Operator.ValuesOnlyMask)] = "op_ExclusiveOr";
-                       oper_names [(int) (Operator.LogicalOr & Operator.ValuesOnlyMask)] = "op_LogicalOr";
-                       oper_names [(int) (Operator.LogicalAnd & Operator.ValuesOnlyMask)] = "op_LogicalAnd";
-               }
-
                public Binary (Operator oper, Expression left, Expression right, bool isCompound)
                        : this (oper, left, right)
                {
@@ -2014,9 +2013,47 @@ namespace Mono.CSharp {
                        Error_OperatorCannotBeApplied (Location, OperName (oper), l, r);
                }
 
-               public static string GetOperatorMetadataName (Operator op)
+               static string GetOperatorMetadataName (Operator op)
                {
-                       return oper_names [(int)(op & Operator.ValuesOnlyMask)];
+                       CSharp.Operator.OpType op_type;
+                       switch (op) {
+                       case Operator.Addition:
+                               op_type = CSharp.Operator.OpType.Addition; break;
+                       case Operator.BitwiseAnd:
+                               op_type = CSharp.Operator.OpType.BitwiseAnd; break;
+                       case Operator.BitwiseOr:
+                               op_type = CSharp.Operator.OpType.BitwiseOr; break;
+                       case Operator.Division:
+                               op_type = CSharp.Operator.OpType.Division; break;
+                       case Operator.Equality:
+                               op_type = CSharp.Operator.OpType.Equality; break;
+                       case Operator.ExclusiveOr:
+                               op_type = CSharp.Operator.OpType.ExclusiveOr; break;
+                       case Operator.GreaterThan:
+                               op_type = CSharp.Operator.OpType.GreaterThan; break;
+                       case Operator.GreaterThanOrEqual:
+                               op_type = CSharp.Operator.OpType.GreaterThanOrEqual; break;
+                       case Operator.Inequality:
+                               op_type = CSharp.Operator.OpType.Inequality; break;
+                       case Operator.LeftShift:
+                               op_type = CSharp.Operator.OpType.LeftShift; break;
+                       case Operator.LessThan:
+                               op_type = CSharp.Operator.OpType.LessThan; break;
+                       case Operator.LessThanOrEqual:
+                               op_type = CSharp.Operator.OpType.LessThanOrEqual; break;
+                       case Operator.Modulus:
+                               op_type = CSharp.Operator.OpType.Modulus; break;
+                       case Operator.Multiply:
+                               op_type = CSharp.Operator.OpType.Multiply; break;
+                       case Operator.RightShift:
+                               op_type = CSharp.Operator.OpType.RightShift; break;
+                       case Operator.Subtraction:
+                               op_type = CSharp.Operator.OpType.Subtraction; break;
+                       default:
+                               throw new InternalErrorException (op.ToString ());
+                       }
+
+                       return CSharp.Operator.GetMetadataName (op_type);
                }
 
                static bool IsUnsigned (Type t)
@@ -2454,8 +2491,6 @@ namespace Mono.CSharp {
 
                        MethodInfo method;
                        ArrayList args = new ArrayList (2);
-
-                       args = new ArrayList (2);
                        args.Add (new Argument (left, Argument.AType.Expression));
                        args.Add (new Argument (right, Argument.AType.Expression));
 
@@ -2475,7 +2510,10 @@ namespace Mono.CSharp {
                                method = TypeManager.delegate_remove_delegate_delegate;
                        }
 
-                       return new BinaryDelegate (l, method, args);
+                       MethodGroupExpr mg = new MethodGroupExpr (new MemberInfo [] { method }, TypeManager.delegate_type, loc);
+                       mg = mg.OverloadResolve (ec, ref args, false, loc);
+
+                       return new ClassCast (new UserOperatorCall (mg, args, CreateExpressionTree, loc), l);
                }
 
                //
@@ -2816,17 +2854,16 @@ namespace Mono.CSharp {
 
                        string op = GetOperatorMetadataName (user_oper);
 
-                       MethodGroupExpr union;
                        MethodGroupExpr left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
-                       if (!TypeManager.IsEqual (r, l)) {
-                               MethodGroupExpr right_operators = MemberLookup (
-                                       ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
-                               union = MethodGroupExpr.MakeUnionSet (left_operators, right_operators, loc);
-                       } else
-                               union = left_operators;
+                       MethodGroupExpr right_operators = null;
 
-                       if (union == null)
+                       if (!TypeManager.IsEqual (r, l)) {
+                               right_operators = MemberLookup (ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+                               if (right_operators == null && left_operators == null)
+                                       return null;
+                       } else if (left_operators == null) {
                                return null;
+                       }
 
                        ArrayList args = new ArrayList (2);
                        Argument larg = new Argument (left);
@@ -2834,6 +2871,30 @@ namespace Mono.CSharp {
                        Argument rarg = new Argument (right);
                        args.Add (rarg);
 
+                       MethodGroupExpr union;
+
+                       //
+                       // User-defined operator implementations always take precedence
+                       // over predefined operator implementations
+                       //
+                       if (left_operators != null && right_operators != null) {
+                               if (IsPredefinedUserOperator (l, user_oper)) {
+                                       union = right_operators.OverloadResolve (ec, ref args, true, loc);
+                                       if (union == null)
+                                               union = left_operators;
+                               } else if (IsPredefinedUserOperator (r, user_oper)) {
+                                       union = left_operators.OverloadResolve (ec, ref args, true, loc);
+                                       if (union == null)
+                                               union = right_operators;
+                               } else {
+                                       union = MethodGroupExpr.MakeUnionSet (left_operators, right_operators, loc);
+                               }
+                       } else if (left_operators != null) {
+                               union = left_operators;
+                       } else {
+                               union = right_operators;
+                       }
+
                        union = union.OverloadResolve (ec, ref args, true, loc);
                        if (union == null)
                                return null;
@@ -2947,6 +3008,14 @@ namespace Mono.CSharp {
                                t == TypeManager.delegate_type || TypeManager.IsDelegateType (t);
                }
 
+               static bool IsPredefinedUserOperator (Type t, Operator op)
+               {
+                       //
+                       // Some predefined types have user operators
+                       //
+                       return (op & Operator.EqualityMask) != 0 && (t == TypeManager.string_type || t == TypeManager.decimal_type);
+               }
+
                private static bool IsTypeIntegral (Type type)
                {
                        return type == TypeManager.uint64_type ||
@@ -3434,40 +3503,6 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (method_name, args);
                }
        }
-
-       //
-       // Object created by Binary when the binary operator uses an method instead of being
-       // a binary operation that maps to a CIL binary operation.
-       //
-       public class BinaryMethod : Expression {
-               public MethodBase method;
-               public ArrayList  Arguments;
-               
-               public BinaryMethod (Type t, MethodBase m, ArrayList args)
-               {
-                       method = m;
-                       Arguments = args;
-                       type = t;
-                       eclass = ExprClass.Value;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       return this;
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       ILGenerator ig = ec.ig;
-                       
-                       Invocation.EmitArguments (ec, Arguments, false, null);
-                       
-                       if (method is MethodInfo)
-                               ig.Emit (OpCodes.Call, (MethodInfo) method);
-                       else
-                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-               }
-       }
        
        //
        // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
@@ -3574,50 +3609,6 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // Object created with +/= on delegates
-       //
-       public class BinaryDelegate : Expression {
-               MethodInfo method;
-               ArrayList  args;
-
-               public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
-               {
-                       method = mi;
-                       this.args = args;
-                       type = t;
-                       eclass = ExprClass.Value;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       return this;
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       ILGenerator ig = ec.ig;
-                       
-                       Invocation.EmitArguments (ec, args, false, null);
-                       
-                       ig.Emit (OpCodes.Call, (MethodInfo) method);
-                       ig.Emit (OpCodes.Castclass, type);
-               }
-
-               public Expression Right {
-                       get {
-                               Argument arg = (Argument) args [1];
-                               return arg.Expr;
-                       }
-               }
-
-               public bool IsAddition {
-                       get {
-                               return method == TypeManager.delegate_combine_delegate_delegate;
-                       }
-               }
-       }
-       
        //
        // User-defined conditional logical operator
        //
@@ -3693,6 +3684,12 @@ namespace Mono.CSharp {
                        is_add = is_addition;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
@@ -4508,6 +4505,9 @@ namespace Mono.CSharp {
 
                public bool Resolve (EmitContext ec, Location loc)
                {
+                       if (Expr == null)
+                               return false;
+
                        using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
                                // Verify that the argument is readable
                                if (ArgType != AType.Out)
@@ -4611,6 +4611,9 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (mg.IsBase)
+                               MemberExpr.Error_BaseAccessInExpressionTree (loc);
+
                        return CreateExpressionFactoryCall ("Call", args);
                }
 
@@ -5014,6 +5017,11 @@ namespace Mono.CSharp {
                        this.loc = expr.Location;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        //
@@ -5750,20 +5758,26 @@ namespace Mono.CSharp {
                {
                        ArrayList args;
 
-                       if (dimensions != 1) {
-                               if (initializers != null) {
-                                       Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
-                                       return null;
-                               }
-
+                       if (array_data == null) {
                                args = new ArrayList (arguments.Count + 1);
                                args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
-                               foreach (Argument a in arguments)
+                               foreach (Argument a in arguments) {
+                                       if (arguments.Count == 1) {
+                                               Constant c = a.Expr as Constant;
+                                               if (c.IsDefaultValue)
+                                                       return CreateExpressionFactoryCall ("NewArrayInit", args);
+                                       }
                                        args.Add (new Argument (a.Expr.CreateExpressionTree (ec)));
+                               }
 
                                return CreateExpressionFactoryCall ("NewArrayBounds", args);
                        }
 
+                       if (dimensions > 1) {
+                               Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
+                               return null;
+                       }
+
                        args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
                        args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
                        if (array_data != null) {
@@ -6617,6 +6631,11 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
@@ -6705,29 +6724,6 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // This produces the value that renders an instance, used by the iterators code
-       //
-       public class ProxyInstance : Expression, IMemoryLocation  {
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       eclass = ExprClass.Variable;
-                       type = ec.ContainerType;
-                       return this;
-               }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
-
-               }
-               
-               public void AddressOf (EmitContext ec, AddressOp mode)
-               {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
-               }
-       }
-
        /// <summary>
        ///   Implements the typeof operator
        /// </summary>
@@ -6961,6 +6957,11 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        if (TypeManager.fieldinfo_get_field_from_handle == null) {
@@ -6997,6 +6998,12 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
@@ -8216,6 +8223,17 @@ namespace Mono.CSharp {
                        throw new NotImplementedException (at.ToString ());
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (arguments.Count + 2);
+                       args.Add (new Argument (instance_expr.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOfMethodInfo (get, loc)));
+                       foreach (Argument a in arguments)
+                               args.Add (new Argument (a.Expr.CreateExpressionTree (ec)));
+
+                       return CreateExpressionFactoryCall ("Call", args);
+               }
+
                protected virtual bool CommonResolve (EmitContext ec)
                {
                        indexer_type = instance_expr.Type;
@@ -8429,6 +8447,11 @@ namespace Mono.CSharp {
                        this.args = args;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        Expression c = CommonResolve (ec);
@@ -8545,6 +8568,12 @@ namespace Mono.CSharp {
 
                        return true;
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       MemberExpr.Error_BaseAccessInExpressionTree (loc);
+                       return base.CreateExpressionTree (ec);
+               }
        }
        
        /// <summary>
@@ -8591,6 +8620,11 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                        loc = Location.Null;
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
@@ -8631,6 +8665,11 @@ namespace Mono.CSharp {
                        loc = Location.Null;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return null;
+               }
+
                public override void EmitStatement (EmitContext ec)
                {
                        // Do nothing
@@ -8668,7 +8707,7 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       ArrayList args = new ArrayList (2);
+                       ArrayList args = new ArrayList (3);
                        args.Add (new Argument (source.CreateExpressionTree (ec)));
                        args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
                        args.Add (new Argument (new TypeOfMethodInfo (method, loc)));
@@ -8795,6 +8834,12 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
+
                public override void Emit(EmitContext ec)
                {
                        array.Emit (ec);
@@ -8837,34 +8882,24 @@ namespace Mono.CSharp {
        //
        // Encapsulates a conversion rules required for array indexes
        //
-       public class ArrayIndexCast : Expression
+       public class ArrayIndexCast : TypeCast
        {
-               Expression expr;
-
                public ArrayIndexCast (Expression expr)
+                       : base (expr, expr.Type)
                {
-                       this.expr = expr;
-                       this.loc = expr.Location;
                }
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
                        ArrayList args = new ArrayList (2);
-                       args.Add (new Argument (expr.CreateExpressionTree (ec)));
+                       args.Add (new Argument (child.CreateExpressionTree (ec)));
                        args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc)));
                        return CreateExpressionFactoryCall ("ConvertChecked", args);
                }
 
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       type = expr.Type;
-                       eclass = expr.eclass;
-                       return this;
-               }
-
                public override void Emit (EmitContext ec)
                {
-                       expr.Emit (ec);
+                       child.Emit (ec);
                                
                        if (type == TypeManager.int32_type)
                                return;
@@ -8880,45 +8915,6 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // Used by the fixed statement
-       //
-       public class StringPtr : Expression {
-               LocalBuilder b;
-               
-               public StringPtr (LocalBuilder b, Location l)
-               {
-                       this.b = b;
-                       eclass = ExprClass.Value;
-                       type = TypeManager.char_ptr_type;
-                       loc = l;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       // This should never be invoked, we are born in fully
-                       // initialized state.
-
-                       return this;
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       if (TypeManager.int_get_offset_to_string_data == null) {
-                               // TODO: Move to resolve !!
-                               TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
-                                       TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
-                       }
-
-                       ILGenerator ig = ec.ig;
-
-                       ig.Emit (OpCodes.Ldloc, b);
-                       ig.Emit (OpCodes.Conv_I);
-                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
-                       ig.Emit (OpCodes.Add);
-               }
-       }
-       
        //
        // Implements the `stackalloc' keyword
        //
@@ -8934,6 +8930,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        count = count.Resolve (ec);
@@ -9305,7 +9306,7 @@ namespace Mono.CSharp {
                        public override Expression CreateExpressionTree (EmitContext ec)
                        {
                                // Should not be reached
-                               throw new NotSupportedException ();
+                               throw new NotSupportedException ("ET");
                        }
 
                        public override Expression DoResolve (EmitContext ec)
@@ -9474,6 +9475,11 @@ namespace Mono.CSharp {
                        return type;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        AnonymousTypeClass anonymous_type;
@@ -9542,6 +9548,11 @@ namespace Mono.CSharp {
                        t.initializer = initializer.Clone (clonectx);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override bool Equals (object o)
                {
                        AnonymousTypeParameter other = o as AnonymousTypeParameter;
index 82b12c89d84e122e298a9b1518afb07dd86dae92..87b366b1b708a2489375ea37dca4e2100fe992d1 100644 (file)
@@ -1136,9 +1136,16 @@ namespace Mono.CSharp
                                FieldInfo field = struct_info.Fields [i];
 
                                if (!branching.IsFieldAssigned (vi, field.Name)) {
-                                       Report.Error (171, loc,
-                                               "Field `{0}' must be fully assigned before control leaves the constructor",
-                                               TypeManager.GetFullNameSignature (field));
+                                       FieldBase fb = TypeManager.GetField (field);
+                                       if (fb != null && (fb.ModFlags & Modifiers.BACKING_FIELD) != 0) {
+                                               Report.Error (843, loc,
+                                                       "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling default contructor",
+                                                       fb.GetSignatureForError ());
+                                       } else {
+                                               Report.Error (171, loc,
+                                                       "Field `{0}' must be fully assigned before control leaves the constructor",
+                                                       TypeManager.GetFullNameSignature (field));
+                                       }
                                        ok = false;
                                }
                        }
index 8d0a9a79655b4e2b74d51cd1f16e888df618ec2c..4ec6bfad3ecb6e6f1a5406b97343feee9de0a4a5 100644 (file)
@@ -993,6 +993,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public static Iterator CreateIterator (IMethodData method, DeclSpace parent,
                                                       GenericMethod generic, int modifiers)
                {
index 80bf5d3cbde28f117bb23f309da8cf1534c51732..b561487a33783739f9d9e3814bbaa76bfcb208a0 100644 (file)
@@ -149,6 +149,11 @@ namespace Mono.CSharp {
                                return "lambda expression";
                        }
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return Block.CreateExpressionTree (ec);
+               }
        }
 
        //
index ff1d2857db7f73681f361b9fbed983677a58f4ab..a7b76aff7d95b30af94362e17d5caa89e1e432b8 100644 (file)
@@ -142,6 +142,12 @@ namespace Mono.CSharp.Linq
                                t.next = (AQueryClause)next.Clone (clonectx);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       // Should not be reached
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        return expr.DoResolve (ec);
@@ -194,7 +200,7 @@ namespace Mono.CSharp.Linq
                        LambdaExpression selector = new LambdaExpression (
                                null, null, (TypeContainer)ec.TypeContainer, p, ec.CurrentBlock, loc);
                        selector.Block = new SelectorBlock (ec.CurrentBlock, p, ti, loc);
-                       selector.Block.AddStatement (new Return (expr, loc));
+                       selector.Block.AddStatement (new ContextualReturn (expr));
 
                        if (!ec.IsInProbingMode) {
                                selector.CreateAnonymousHelpers ();
@@ -664,6 +670,11 @@ namespace Mono.CSharp.Linq
                                // Nothing to clone
                        }
 
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               throw new NotSupportedException ();
+                       }
+
                        public override Expression DoResolve (EmitContext ec)
                        {
                                throw new NotSupportedException ();
index 77193f4da119310b0592d5ccc4e3cc897a3b5079..77582d130afa3d1106ac96de87026e6a616ce81c 100644 (file)
@@ -106,8 +106,11 @@ namespace Mono.CSharp {
                        get { return true; }
                }
 
-               public override bool IsNegative 
-               {
+               public override bool IsLiteral {
+                       get { return true; }
+               }
+
+               public override bool IsNegative {
                        get { return false; }
                }
 
@@ -115,8 +118,7 @@ namespace Mono.CSharp {
                        get { return true; }
                }
 
-               public override bool IsZeroInteger 
-               {
+               public override bool IsZeroInteger {
                        get { return true; }
                }
 
@@ -161,6 +163,10 @@ namespace Mono.CSharp {
                        type = TypeManager.bool_type;
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
 
        public class CharLiteral : CharConstant {
@@ -173,6 +179,10 @@ namespace Mono.CSharp {
                        type = TypeManager.char_type;
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
 
        public class IntLiteral : IntConstant {
@@ -201,6 +211,9 @@ namespace Mono.CSharp {
                        return base.ConvertImplicitly (type);
                }
 
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
 
        public class UIntLiteral : UIntConstant {
@@ -213,6 +226,10 @@ namespace Mono.CSharp {
                        type = TypeManager.uint32_type;
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
        
        public class LongLiteral : LongConstant {
@@ -223,9 +240,12 @@ namespace Mono.CSharp {
                public override Expression DoResolve (EmitContext ec)
                {
                        type = TypeManager.int64_type;
-
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
 
        public class ULongLiteral : ULongConstant {
@@ -238,6 +258,10 @@ namespace Mono.CSharp {
                        type = TypeManager.uint64_type;
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
        
        public class FloatLiteral : FloatConstant {
@@ -251,6 +275,11 @@ namespace Mono.CSharp {
                        type = TypeManager.float_type;
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
+
        }
 
        public class DoubleLiteral : DoubleConstant {
@@ -286,6 +315,11 @@ namespace Mono.CSharp {
                                "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
                                type, suffix);
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
+
        }
 
        public class DecimalLiteral : DecimalConstant {
@@ -298,6 +332,10 @@ namespace Mono.CSharp {
                        type = TypeManager.decimal_type;
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
        }
 
        public class StringLiteral : StringConstant {
@@ -311,5 +349,10 @@ namespace Mono.CSharp {
 
                        return this;
                }
+
+               public override bool IsLiteral {
+                       get { return true; }
+               }
+
        }
 }
index dae3dd86a09a5e6323df8e680d7394d3b4db07a3..0a1ddbb52e19cec6ae57df28756a3bc34c37e5a3 100644 (file)
@@ -34,10 +34,11 @@ namespace Mono.CSharp {
                //
                public const int METHOD_YIELDS                  = 0x8000;
                public const int METHOD_GENERIC                 = 0x10000;
-               public const int PARTIAL                                        = 0x20000;
+               public const int PARTIAL                                = 0x20000;
                public const int DEFAULT_ACCESS_MODIFER = 0x40000;
                public const int METHOD_EXTENSION               = 0x80000;
                public const int COMPILER_GENERATED             = 0x100000;
+               public const int BACKING_FIELD                  = 0x200000 | COMPILER_GENERATED;
 
                public const int Accessibility =
                        PUBLIC | PROTECTED | INTERNAL | PRIVATE;
index 5e92d7e41855d4ecf65271920054e26865397da1..2c179ecd644ee745650b35d54ff37519fdc9c2ac 100644 (file)
@@ -80,44 +80,6 @@ namespace Mono.CSharp.Nullable
                        Constructor = type.GetConstructor (new Type[] { UnderlyingType });
                }
        }
-       
-       public class HasValue : Expression
-       {
-               Expression expr;
-               NullableInfo info;
-
-               private HasValue (Expression expr)
-               {
-                       this.expr = expr;
-               }
-               
-               public static Expression Create (Expression expr, EmitContext ec)
-               {
-                       return new HasValue (expr).Resolve (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       IMemoryLocation memory_loc = expr as IMemoryLocation;
-                       if (memory_loc == null) {
-                               LocalTemporary temp = new LocalTemporary (expr.Type);
-                               expr.Emit (ec);
-                               temp.Store (ec);
-                               memory_loc = temp;
-                       }
-                       memory_loc.AddressOf (ec, AddressOp.LoadStore);
-                       ec.ig.EmitCall (OpCodes.Call, info.HasValue, null);
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       this.info = new NullableInfo (expr.Type);
-
-                       type = TypeManager.bool_type;
-                       eclass = expr.eclass;
-                       return this;
-               }
-       }               
 
        public class Unwrap : Expression, IMemoryLocation, IAssignMethod
        {
@@ -265,6 +227,11 @@ namespace Mono.CSharp.Nullable
                                eclass = ExprClass.Value;
                        }
 
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               throw new NotSupportedException ("ET");
+                       }
+
                        public override Expression DoResolve (EmitContext ec)
                        {
                                return this;
@@ -979,6 +946,9 @@ namespace Mono.CSharp.Nullable
                
                public override Expression CreateExpressionTree (EmitContext ec)
                {
+                       if (left is NullLiteral)
+                               Report.Error (845, loc, "An expression tree cannot contain a coalescing operator with null left side");
+
                        UserCast uc = left as UserCast;
                        Expression conversion = null;
                        if (uc != null) {
@@ -1028,6 +998,13 @@ namespace Mono.CSharp.Nullable
                                        type = expr.Type;
                                        return this;
                                }
+                       } else if (left.IsNull) {
+                               if (!Convert.ImplicitConversionExists (ec, right, TypeManager.object_type)) {
+                                       Binary.Error_OperatorCannotBeApplied (loc, "??", ltype, rtype);
+                                       return null;
+                               }
+                       
+                               return ReducedExpression.Create (right, this).Resolve (ec);
                        } else if (!TypeManager.IsReferenceType (ltype)) {
                                Binary.Error_OperatorCannotBeApplied (loc, "??", ltype, rtype);
                                return null;
@@ -1108,6 +1085,11 @@ namespace Mono.CSharp.Nullable
                        eclass = ExprClass.Value;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return new SimpleAssign (this, this).CreateExpressionTree (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        expr = expr.Resolve (ec);
index 0dcd753f977c0727c899f46a65829b49c0ca9727..72b3a610170f33ffe384e0f6d774bad21997d26c 100644 (file)
@@ -4160,6 +4160,48 @@ namespace Mono.CSharp {
                }
 
                class StringEmitter : Emitter {
+                       class StringPtr : Expression
+                       {
+                               LocalBuilder b;
+
+                               public StringPtr (LocalBuilder b, Location l)
+                               {
+                                       this.b = b;
+                                       eclass = ExprClass.Value;
+                                       type = TypeManager.char_ptr_type;
+                                       loc = l;
+                               }
+
+                               public override Expression CreateExpressionTree (EmitContext ec)
+                               {
+                                       throw new NotSupportedException ("ET");
+                               }
+
+                               public override Expression DoResolve (EmitContext ec)
+                               {
+                                       // This should never be invoked, we are born in fully
+                                       // initialized state.
+
+                                       return this;
+                               }
+
+                               public override void Emit (EmitContext ec)
+                               {
+                                       if (TypeManager.int_get_offset_to_string_data == null) {
+                                               // TODO: Move to resolve !!
+                                               TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
+                                                       TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
+                                       }
+
+                                       ILGenerator ig = ec.ig;
+
+                                       ig.Emit (OpCodes.Ldloc, b);
+                                       ig.Emit (OpCodes.Conv_I);
+                                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
+                                       ig.Emit (OpCodes.Add);
+                               }
+                       }
+
                        LocalBuilder pinned_string;
                        Location loc;
 
index 431b329f04ed42762464641a356a3812efc8f5b0..30a705ee960775259c59a644ea5beedc726dbd6f 100644 (file)
@@ -768,10 +768,10 @@ namespace Mono.CSharp {
                int accessor_end = 0;
 
                if (!mb.IsConstructor && TypeManager.IsSpecialMethod (mb)) {
-                       Operator.OpType ot = Operator.GetOperatorType (mb.Name);
-                       if (ot != Operator.OpType.TOP) {
+                       string op_name = Operator.GetName (mb.Name);
+                       if (op_name != null) {
                                sig.Append ("operator ");
-                               sig.Append (Operator.GetName (ot));
+                               sig.Append (op_name);
                                sig.Append (parameters);
                                return sig.ToString ();
                        }
@@ -3255,17 +3255,9 @@ namespace Mono.CSharp {
                        return true;
 
                string name = mb.Name;
-               if (name.StartsWith ("op_")){
-                       foreach (string oname in Unary.oper_names) {
-                               if (oname == name)
-                                       return true;
-                       }
+               if (name.StartsWith ("op_"))
+                       return Operator.GetName (name) != null;
 
-                       foreach (string oname in Binary.oper_names) {
-                               if (oname == name)
-                                       return true;
-                       }
-               }
                return false;
        }
 
diff --git a/mcs/tests/gtest-391.cs b/mcs/tests/gtest-391.cs
new file mode 100644 (file)
index 0000000..de34b37
--- /dev/null
@@ -0,0 +1,18 @@
+using System;
+
+class C
+{
+       public static int Main ()
+       {
+               string a = null;
+               string b = null ?? "a";
+               if (b != "a")
+                       return 1;
+               
+               int? i = null ?? null;
+               if (i != null)
+                       return 2;
+               
+               return 0;
+       }
+}
\ No newline at end of file
index 5350fd9c935798bfdb6f6eeb08d90b66153fda5a..162baed6518e47226d1504282ea232cbbcfa1ac2 100644 (file)
@@ -1,3 +1,5 @@
+// Compiler options: -unsafe
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -47,12 +49,14 @@ public struct MyType<T>
 public struct MyType
 {
        int value;
-
-       public MyType (int value)
+       
+       public MyType (int value) : this ()
        {
                this.value = value;
        }
        
+       public short ShortProp { get; set; }
+       
        public override int GetHashCode ()
        {
                throw new NotImplementedException ();
@@ -227,7 +231,13 @@ class MemberAccessData
                get {
                        return mt;
                }
-       }       
+       }
+       
+       public static string StaticProperty {
+               get {
+                       return "alo";
+               }
+       }
 }
 
 enum MyEnum : byte
@@ -275,6 +285,12 @@ class NewTest<T>
        }
 }
 
+class Indexer
+{
+       public int this [int i] { get { return i; } set { } }
+       public string this [params string[] i] { get { return string.Concat (i); } }
+}
+
 
 // TODO: Add more nullable tests, follow AddTest pattern.
 
@@ -499,6 +515,10 @@ class Tester
 
                decimal [] [] array = { new decimal [] { 1, 9 }, new decimal [] { 10, 90 } };
                Assert (90, e4.Compile ().Invoke (array, 1));
+               
+               Expression<Func<int>> e5 = () => (new int [1]) [0];
+               AssertNodeType (e5, ExpressionType.ArrayIndex);
+               Assert (0, e5.Compile ().Invoke ());
        }
 
        void ArrayLengthTest ()
@@ -508,9 +528,9 @@ class Tester
                Assert (0, e.Compile ().Invoke (new double [0]));
                Assert (9, e.Compile ().Invoke (new double [9]));
 
-               //Expression<Func<string [,], int>> e2 = (string [,] a) => a.Length;
-               //AssertNodeType (e2, ExpressionType.MemberAccess);
-               //Assert (0, e2.Compile ().Invoke (new string [0, 0]));
+               Expression<Func<string [,], int>> e2 = (string [,] a) => a.Length;
+               AssertNodeType (e2, ExpressionType.MemberAccess);
+               Assert (0, e2.Compile ().Invoke (new string [0, 0]));
        }
 
        void CallTest ()
@@ -538,7 +558,19 @@ class Tester
                
                Expression<Action> e6 = () => Console.WriteLine ("call test");
                AssertNodeType (e6, ExpressionType.Call);
-       }
+               
+               Expression<Func<Indexer, int, int>> e7 = (a, b) => a [b];
+               AssertNodeType (e7, ExpressionType.Call);
+               Assert (3, e7.Compile ().Invoke (new Indexer (), 3));
+
+               Expression<Func<Indexer, string, string, string, string>> e8 = (a, b, c , d) => a [b, c, d];
+               AssertNodeType (e8, ExpressionType.Call);
+               Assert ("zyb", e8.Compile ().Invoke (new Indexer (), "z", "y", "b"));
+               
+               Expression<Action<int>> e9 = (a) => RefMethod (ref a);
+               AssertNodeType (e9, ExpressionType.Call);
+               e9.Compile ().Invoke (1);
+       }               
 
        void CoalesceTest ()
        {
@@ -585,9 +617,9 @@ class Tester
        
        void ConstantTest ()
        {
-//             Expression<Func<int>> e1 = () => default (int);
-//             AssertNodeType (e1, ExpressionType.Constant);
-//             Assert (0, e1.Compile ().Invoke ());
+               Expression<Func<int>> e1 = () => default (int);
+               AssertNodeType (e1, ExpressionType.Constant);
+               Assert (0, e1.Compile ().Invoke ());
 
                Expression<Func<int?>> e2 = () => default (int?);
                AssertNodeType (e2, ExpressionType.Constant);
@@ -634,6 +666,16 @@ class Tester
                Expression<Func<MyEnum>> e12 = () => new MyEnum ();
                AssertNodeType (e12, ExpressionType.Constant);
                Assert<MyEnum> (0, e12.Compile ().Invoke ());
+               
+               Expression<Func<int>> e13 = () => sizeof (byte);
+               AssertNodeType (e13, ExpressionType.Constant);
+               Assert (1, e13.Compile ().Invoke ());
+               
+               unsafe {
+                       Expression<Func<Type>> e14 = () => typeof (bool*);
+                       AssertNodeType (e14, ExpressionType.Constant);
+                       Assert (typeof (bool*), e14.Compile ().Invoke ());
+               }
        }
 
        void ConvertTest ()
@@ -663,12 +705,47 @@ class Tester
                Assert (true, e6.Compile ().Invoke (null, null));
                Assert (true, e6.Compile ().Invoke (new MyType (120), new MyType (120)));
                
-               // TODO: redundant return conversion
-               // Expression<Func<MyTypeExplicit, int?>> e6 = x => (int?)x;
+               Expression<Func<MyTypeExplicit, int?>> e7 = x => (int?)x;
+               AssertNodeType (e7, ExpressionType.Convert);
+               Assert (33, e7.Compile ().Invoke (new MyTypeExplicit (33)));
                
-               // TODO: redundant convert
-               // TODO: pass null value
-               // Expression<Func<int?, object>> ex = x => (object)x;
+               Expression<Func<int?, object>> e8 = x => (object)x;
+               AssertNodeType (e8, ExpressionType.Convert);
+               Assert (null, e8.Compile ().Invoke (null));
+               Assert (-100, e8.Compile ().Invoke (-100));
+               
+               unsafe {
+                       int*[] p = new int* [1];
+                       Expression<Func<object>> e9 = () => (object)p;
+                       AssertNodeType (e9, ExpressionType.Convert);
+                       Assert (p, e9.Compile ().Invoke ());
+               }
+               
+               Expression<Func<Func<int>, Delegate>> e10 = (a) => a + a;
+               AssertNodeType (e10, ExpressionType.Convert);
+               Assert (null, e10.Compile ().Invoke (null));
+               Assert (new Func<int> (TestInt) + new Func<int> (TestInt), e10.Compile ().Invoke (TestInt));
+               
+               Expression<Func<Func<int>, Delegate>> e11 = (a) => a - a;
+               AssertNodeType (e11, ExpressionType.Convert);
+               Assert (null, e11.Compile ().Invoke (null));
+               
+               Expression<Func<Func<int>>> e12 = () => TestInt;
+               AssertNodeType (e12, ExpressionType.Convert);
+               Assert (29, e12.Compile ().Invoke () ());
+               
+               Expression<Func<decimal, sbyte>> e13 = a => (sbyte)a;
+               AssertNodeType (e13, ExpressionType.Convert);
+               Assert (6, e13.Compile ().Invoke (6));
+               
+               Expression<Func<long, decimal>> e14 = a => a;
+               AssertNodeType (e14, ExpressionType.Convert);
+               Assert (-66, e14.Compile ().Invoke (-66));
+
+               Expression<Func<ulong?, decimal?>> e15 = a => a;
+               AssertNodeType (e15, ExpressionType.Convert);
+               Assert (null, e15.Compile ().Invoke (null));
+               Assert (9, e15.Compile ().Invoke (9));
        }
 
        void ConvertCheckedTest ()
@@ -1100,6 +1177,26 @@ class Tester
                var e5 = d.GetEvent ();
                AssertNodeType (e5, ExpressionType.MemberAccess);
                Assert (null, e5.Compile ().Invoke ());
+               
+               Expression<Func<MyType>> e6 = () => d.MyTypeProperty;
+               AssertNodeType (e6, ExpressionType.MemberAccess);
+               Assert (new MyType (), e6.Compile ().Invoke ());
+
+               Expression<Func<MyType, short>> e7 = a => a.ShortProp;
+               AssertNodeType (e7, ExpressionType.MemberAccess);
+               MyType mt = new MyType ();
+               mt.ShortProp = 124;
+               Assert (124, e7.Compile ().Invoke (mt));
+
+               Expression<Func<string>> e8 = () => MemberAccessData.StaticProperty;
+               AssertNodeType (e8, ExpressionType.MemberAccess);
+               Assert ("alo", e8.Compile ().Invoke ());
+               
+               string s = "localvar";
+               Expression<Func<string>> e9 = () => s;
+               // CSC emits this as MemberAccess
+               AssertNodeType (e9, ExpressionType.Constant);
+               Assert ("localvar", e9.Compile ().Invoke ());
        }
        
        void MemberInitTest ()
@@ -1120,6 +1217,11 @@ class Tester
                AssertNodeType (e2, ExpressionType.MemberInit);
                var r2 = e2.Compile ().Invoke ();
                Assert ("a", r2.ListValues [0]);
+               
+               Expression<Func<short, MyType>> e3 = a => new MyType { ShortProp = a };
+               AssertNodeType (e3, ExpressionType.MemberInit);
+               var r3 = e3.Compile ().Invoke (33);
+               Assert (33, r3.ShortProp);
        }       
 
        void ModuloTest ()
@@ -1295,9 +1397,9 @@ class Tester
                AssertNodeType (e, ExpressionType.NewArrayInit);
                Assert (new int [0], e.Compile ().Invoke ());
 
-               e = () => new int [] { };
-               AssertNodeType (e, ExpressionType.NewArrayInit);
-               Assert (new int [0], e.Compile ().Invoke ());
+               Expression<Func<int []>> e1 = () => new int [] { };
+               AssertNodeType (e1, ExpressionType.NewArrayInit);
+               Assert (new int [0], e1.Compile ().Invoke ());
 
                Expression<Func<ushort, ulong? []>> e2 = (ushort a) => new ulong? [] { a };
                AssertNodeType (e2, ExpressionType.NewArrayInit);
@@ -1313,6 +1415,10 @@ class Tester
                Expression<Func<int [,]>> e = () => new int [2,3];
                AssertNodeType (e, ExpressionType.NewArrayBounds);
                Assert (new int [2,3].Length, e.Compile ().Invoke ().Length);
+               
+               Expression<Func<int[,]>> e2 = () => new int [0,0];
+               AssertNodeType (e2, ExpressionType.NewArrayBounds);
+               Assert (new int [0, 0].Length, e2.Compile ().Invoke ().Length);
        }       
        
        void NewTest ()
@@ -1543,6 +1649,15 @@ class Tester
                Expression<Func<IntPtr, IntPtr>> e3 = a => a;
                AssertNodeType (e3, ExpressionType.Parameter);
                Assert (IntPtr.Zero, e3.Compile ().Invoke (IntPtr.Zero));
+               
+               unsafe {
+                       Expression<Func<int*[], int* []>> e4 = (a) => a;
+                       AssertNodeType (e4, ExpressionType.Parameter);
+                       Assert<int*[]> (null, e4.Compile ().Invoke (null));
+                       int* e4_el = stackalloc int [5];
+                       int*[] ptr = new int*[] { e4_el };
+                       Assert<int*[]> (ptr, e4.Compile ().Invoke (ptr));
+               }
        }
 
        void QuoteTest ()
@@ -1697,6 +1812,11 @@ class Tester
                Expression<Func<bool>> e5 = () => 1 is int;
                AssertNodeType (e5, ExpressionType.TypeIs);
                Assert (true, e5.Compile ().Invoke ());
+               
+               Expression<Func<int?, bool>> e6 = (a) => a is int;
+               AssertNodeType (e6, ExpressionType.TypeIs);
+               Assert (true, e6.Compile ().Invoke (1));
+               Assert (false, e6.Compile ().Invoke (null));
        }
        
        void UnaryPlus ()
@@ -1749,7 +1869,11 @@ class Tester
        {
                return t;
        }
-
+       
+       static void RefMethod (ref int i)
+       {
+               i = 867;
+       }
 
        public static int Main ()
        {
index 017f5d585b9c1b345cf19e9d7375adbdeb3640f6..067717a7f1e6bb808baaceb6a60a9eeee03f22fd 100644 (file)
@@ -1,7 +1,10 @@
+// Compiler options: -unsafe
+
 using System;
 using System.Linq.Expressions;
 
 delegate void EmptyDelegate ();
+unsafe delegate int* UnsafeDelegate ();
 
 class C
 {
@@ -12,6 +15,11 @@ class C
                i += 9;
        }
        
+       static unsafe int* Foo ()
+       {
+               return (int*)1;
+       }
+       
        public static int Main ()
        {
                Expression<Func<EmptyDelegate>> e = () => new EmptyDelegate (Test);
@@ -27,14 +35,26 @@ class C
                
                Expression<Func<EmptyDelegate>> e2 = () => Test;
                if (e2.Body.ToString () != "Convert(CreateDelegate(EmptyDelegate, null, Void Test()))")
-                       return 1;
+                       return 3;
 
                var v2 = e2.Compile ();
                v2.Invoke ()();
                
                if (i != 18)
-                       return 2;
+                       return 4;
+                       
+               unsafe {
+                       Expression<Func<UnsafeDelegate>> e3 = () => new UnsafeDelegate (Foo);
+                       if (e3.Body.ToString () != "Convert(CreateDelegate(UnsafeDelegate, null, Int32* Foo()))")
+                               return 5;
+                       
+                       var v3 = e3.Compile ();
+                       if (v3.Invoke ()() != (int*)1)
+                               return 6;
+               }
 
+               Console.WriteLine ("OK");
                return 0;
        }
 }
+
diff --git a/mcs/tests/test-641.cs b/mcs/tests/test-641.cs
new file mode 100644 (file)
index 0000000..c128d5e
--- /dev/null
@@ -0,0 +1,46 @@
+using System;
+
+public class Identifier
+{
+       public Identifier () { }
+
+       public static bool operator == (Identifier id1, Identifier id2)
+       {
+               return true;
+       }
+       public static bool operator != (Identifier id1, Identifier id2)
+       {
+               return true;
+       }
+
+       public static implicit operator Identifier (string identifier)
+       {
+               return null;
+       }
+       
+       public static implicit operator String (Identifier id)
+       {
+               return null;
+       }
+       
+       public static implicit operator decimal (Identifier id)
+       {
+               return -1;
+       }       
+
+       static int Main ()
+       {
+               Identifier a = null;
+               string b = "a";
+
+               if (!(a == b))
+                       return 1;
+
+               decimal d = 5;
+               if (a == d)
+                       return 2;
+               
+               return 0;
+       }
+}
+
index 996c34d2a63a519172e706bdfa134301bfc9b8ea..244adcf499f85193a219efa9ede7adcf72a77919 100644 (file)
         <size>10</size>
       </method>
       <method name="Int32 TestC()">
-        <size>34</size>
+        <size>36</size>
       </method>
       <method name="Int32 Main()">
         <size>107</size>
       </method>
     </type>
   </test>
+  <test name="gtest-391.cs">
+    <type name="C">
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>55</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-anon-1.cs">
     <type name="X">
       <method name="Void .ctor()">
       </method>
     </type>
   </test>
+  <test name="test-641.cs">
+    <type name="Identifier">
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>55</size>
+      </method>
+      <method name="Boolean op_Equality(Identifier, Identifier)">
+        <size>2</size>
+      </method>
+      <method name="Boolean op_Inequality(Identifier, Identifier)">
+        <size>2</size>
+      </method>
+      <method name="Identifier op_Implicit(System.String)">
+        <size>2</size>
+      </method>
+      <method name="System.String op_Implicit(Identifier)">
+        <size>2</size>
+      </method>
+      <method name="Decimal op_Implicit(Identifier)">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-65.cs">
     <type name="X">
       <method name="Void .ctor()">
index 9e227f11ec408e428567964ca095220a0350d52c..bba0c4558d35a5f59c4aa117907fc9cdcff6b021 100644 (file)
@@ -1,3 +1,22 @@
+2008-05-01  Zoltan Varga  <vargaz@gmail.com>
+
+       * sgen-gc.c: Implement thread-local allocation and a managed allocation routine.
+
+2008-05-01  Dick Porter  <dick@ximian.com>
+
+       * process.c (process_get_fileversion): Only pass 16 bits of
+       language ID to VerLanguageName.  Fixes bug 381204.
+
+2008-04-30 Rodrigo Kumpera  <rkumpera@novell.com>
+
+       * verify.c (mono_method_verify): Fix the comparison
+       operator for code bounds check.
+
+2008-04-30 Rodrigo Kumpera  <rkumpera@novell.com>
+
+       * verify.c (mono_method_verify): Check the bounds of
+       all access of the code array.
+
 2008-04-29  Kornél Pál  <kornelpal@gmail.com>
 
        * appdomain.c: Use HAVE_SYS_UTIME_H that fixes MSVC build.
index da9844db0bd5eafd52adfcde494ce60461d57956..25c4ebd72fa63906434af59983f2e640b5f13db2 100644 (file)
@@ -307,7 +307,12 @@ static void process_get_fileversion (MonoObject *filever, gunichar2 *filename)
                                                (trans_data[1] << 8) |
                                                (trans_data[2] << 16) |
                                                (trans_data[3] << 24);
-                                       lang_count = VerLanguageName (lang, lang_buf, 128);
+                                       /* Only give the lower 16 bits
+                                        * to VerLanguageName, as
+                                        * Windows gets confused
+                                        * otherwise
+                                        */
+                                       lang_count = VerLanguageName (lang & 0xFFFF, lang_buf, 128);
                                        if (lang_count) {
                                                process_set_field_string (filever, "language", lang_buf, lang_count);
                                        }
index 1c1c20fcd9797a06a9d91c01f0fa36cfb90c2dfd..2c013ddab19e77e430399aa2d24207b5ad703849 100644 (file)
 #include "metadata/threads.h"
 #include "metadata/sgen-gc.h"
 #include "metadata/mono-gc.h"
+#include "metadata/method-builder.h"
+#include "metadata/profiler-private.h"
 #include "utils/mono-mmap.h"
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
 #include <valgrind/memcheck.h>
 #endif
 
+#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
+       a = i,
+
+enum {
+#include "mono/cil/opcode.def"
+       CEE_LAST
+};
+
+#undef OPDEF
+
 /*
  * ######################################################################
  * ########  Types and constants used by the GC.
@@ -176,7 +188,7 @@ mono_gc_flush_info (void)
 }
 
 #define MAX_DEBUG_LEVEL 9
-#define DEBUG(level,a) do {if ((level) <= MAX_DEBUG_LEVEL && (level) <= gc_debug_level) a;} while (0)
+#define DEBUG(level,a) do {if (G_UNLIKELY ((level) <= MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) a;} while (0)
 
 #define TV_DECLARE(name) struct timeval name
 #define TV_GETTIME(tv) gettimeofday (&(tv), NULL)
@@ -293,6 +305,8 @@ struct _PinnedChunk {
  * We should start assigning threads very small fragments: if there are many
  * threads the nursery will be full of reserved space that the threads may not
  * use at all, slowing down allocation speed.
+ * Thread local allocation is done from areas of memory Hotspot calls Thread Local 
+ * Allocation Buffers (TLABs).
  */
 typedef struct _Fragment Fragment;
 
@@ -417,7 +431,7 @@ safe_object_get_size (MonoObject* o)
 }
 
 static inline gboolean
-is_half_constructed (MonoObject *o)
+is_maybe_half_constructed (MonoObject *o)
 {
        MonoClass *klass;
 
@@ -539,27 +553,46 @@ static int num_roots_entries = 0;
  * The current allocation cursors
  * We allocate objects in the nursery.
  * The nursery is the area between nursery_start and nursery_real_end.
- * nursery_next is the pointer to the space where the next object will be allocated.
- * nursery_temp_end is the pointer to the end of the temporary space reserved for
- * the allocation: this allows us to allow allocations inside the fragments of the
- * nursery (the empty holes between pinned objects) and it allows us to set the
- * scan starts at reasonable intervals.
- * nursery_next and nursery_temp_end will become per-thread vars to allow lock-free
- * allocations.
+ * Allocation is done from a Thread Local Allocation Buffer (TLAB). TLABs are allocated
+ * from nursery fragments.
+ * tlab_next is the pointer to the space inside the TLAB where the next object will 
+ * be allocated.
+ * tlab_temp_end is the pointer to the end of the temporary space reserved for
+ * the allocation: it allows us to set the scan starts at reasonable intervals.
+ * tlab_real_end points to the end of the TLAB.
+ * nursery_frag_real_end points to the end of the currently used nursery fragment.
  * nursery_first_pinned_start points to the start of the first pinned object in the nursery
  * nursery_last_pinned_end points to the end of the last pinned object in the nursery
  * At the next allocation, the area of the nursery where objects can be present is
  * between MIN(nursery_first_pinned_start, first_fragment_start) and
- * MAX(nursery_last_pinned_end, nursery_temp_end)
+ * MAX(nursery_last_pinned_end, nursery_frag_real_end)
  */
 static char *nursery_start = NULL;
+
+/*
+ * FIXME: What is faster, a TLS variable pointing to a structure, or separate TLS 
+ * variables for next+temp_end ?
+ */
+static __thread char *tlab_start;
+static __thread char *tlab_next;
+static __thread char *tlab_temp_end;
+static __thread char *tlab_real_end;
+/* Used by the managed allocator */
+static __thread char **tlab_next_addr;
 static char *nursery_next = NULL;
-static char *nursery_temp_end = NULL;
-static char *nursery_real_end = NULL;
 static char *nursery_frag_real_end = NULL;
+static char *nursery_real_end = NULL;
 static char *nursery_first_pinned_start = NULL;
 static char *nursery_last_pinned_end = NULL;
 
+/* The size of a TLAB */
+/* The bigger the value, the less often we have to go to the slow path to allocate a new 
+ * one, but the more space is wasted by threads not allocating much memory.
+ * FIXME: Tune this.
+ * FIXME: Make this self-tuning for each thread.
+ */
+static guint32 tlab_size = (1024 * 4);
+
 /* fragments that are free and ready to be used for allocation */
 static Fragment *nursery_fragments = NULL;
 /* freeelist of fragment structures */
@@ -624,6 +657,8 @@ static void null_link_in_range (char *start, char *end);
 static gboolean search_fragment_for_size (size_t size);
 static void mark_pinned_from_addresses (PinnedChunk *chunk, void **start, void **end);
 static void clear_remsets (void);
+static void clear_tlabs (void);
+static char *find_tlab_next_from_address (char *addr);
 static void sweep_pinned_objects (void);
 static void free_large_object (LOSObject *obj);
 static void free_mem_section (GCMemSection *section);
@@ -1843,7 +1878,6 @@ alloc_nursery (void)
        data = get_os_memory (nursery_size, TRUE);
        nursery_start = nursery_next = data;
        nursery_real_end = data + nursery_size;
-       nursery_temp_end = data + SCAN_START_SIZE;
        UPDATE_HEAP_BOUNDARIES (nursery_start, nursery_real_end);
        total_alloc += nursery_size;
        DEBUG (4, fprintf (gc_debug_file, "Expanding heap size: %zd, total: %zd\n", nursery_size, total_alloc));
@@ -2020,7 +2054,7 @@ drain_gray_stack (char *start_addr, char *end_addr)
 static int last_num_pinned = 0;
 
 static void
-build_nursery_fragments (int start_pin, int end_pin, char *nursery_last_allocated)
+build_nursery_fragments (int start_pin, int end_pin)
 {
        char *frag_start, *frag_end;
        size_t frag_size;
@@ -2051,10 +2085,23 @@ build_nursery_fragments (int start_pin, int end_pin, char *nursery_last_allocate
                 * (zero initialized) object. Find the end of the object by scanning forward.
                 * 
                 */
-               if (is_half_constructed (pin_queue [i])) {
-                       /* Can't use nursery_next as the limit as it is modified in collect_nursery () */
-                       while ((frag_start < nursery_last_allocated) && *(mword*)frag_start == 0)
-                               frag_start += sizeof (mword);
+               if (is_maybe_half_constructed (pin_queue [i])) {
+                       char *tlab_end;
+
+                       /* This is also hit for zero length arrays/strings */
+
+                       /* Find the end of the TLAB which contained this allocation */
+                       tlab_end = find_tlab_next_from_address (pin_queue [i]);
+
+                       if (tlab_end) {
+                               while ((frag_start < tlab_end) && *(mword*)frag_start == 0)
+                                       frag_start += sizeof (mword);
+                       } else {
+                               /*
+                                * FIXME: The object is either not allocated in a TLAB, or it isn't a
+                                * half constructed object.
+                                */
+                       }
                }
        }
        nursery_last_pinned_end = frag_start;
@@ -2069,6 +2116,9 @@ build_nursery_fragments (int start_pin, int end_pin, char *nursery_last_allocate
                }
                degraded_mode = 1;
        }
+
+       /* Clear TLABs for all threads */
+       clear_tlabs ();
 }
 
 /* FIXME: later reduce code duplication here with the above
@@ -2135,14 +2185,12 @@ collect_nursery (size_t requested_size)
        GCMemSection *section;
        size_t max_garbage_amount;
        int i;
-       char *nursery_last_allocated;
        TV_DECLARE (all_atv);
        TV_DECLARE (all_btv);
        TV_DECLARE (atv);
        TV_DECLARE (btv);
 
        degraded_mode = 0;
-       nursery_last_allocated = nursery_next;
        nursery_next = MAX (nursery_next, nursery_last_pinned_end);
        /* FIXME: optimize later to use the higher address where an object can be present */
        nursery_next = MAX (nursery_next, nursery_real_end);
@@ -2210,7 +2258,7 @@ collect_nursery (size_t requested_size)
         * pinned objects as we go, memzero() the empty fragments so they are ready for the
         * next allocations.
         */
-       build_nursery_fragments (0, next_pin_slot, nursery_last_allocated);
+       build_nursery_fragments (0, next_pin_slot);
        TV_GETTIME (atv);
        DEBUG (2, fprintf (gc_debug_file, "Fragment creation: %d usecs, %zd bytes available\n", TV_ELAPSED (btv, atv), fragment_total));
 
@@ -2404,7 +2452,7 @@ major_collection (void)
         * pinned objects as we go, memzero() the empty fragments so they are ready for the
         * next allocations.
         */
-       build_nursery_fragments (nursery_section->pin_queue_start, nursery_section->pin_queue_end, nursery_next);
+       build_nursery_fragments (nursery_section->pin_queue_start, nursery_section->pin_queue_end);
 
        TV_GETTIME (all_btv);
        mono_stats.major_gc_time_usecs += TV_ELAPSED (all_atv, all_btv);
@@ -2496,11 +2544,13 @@ minor_collect_or_expand_inner (size_t size)
                if (!search_fragment_for_size (size)) {
                        int i;
                        /* TypeBuilder and MonoMethod are killing mcs with fragmentation */
-                       DEBUG (1, fprintf (gc_debug_file, "nursery collection didn't find enough room for %zd alloc (%d pinned)", size, last_num_pinned));
+                       DEBUG (1, fprintf (gc_debug_file, "nursery collection didn't find enough room for %zd alloc (%d pinned)\n", size, last_num_pinned));
                        for (i = 0; i < last_num_pinned; ++i) {
                                DEBUG (3, fprintf (gc_debug_file, "Bastard pinning obj %p (%s), size: %d\n", pin_queue [i], safe_name (pin_queue [i]), safe_object_get_size (pin_queue [i])));
                        }
                        degraded_mode = 1;
+                       /* This is needed by collect_nursery () to calculate nursery_last_allocated */
+                       nursery_next = nursery_frag_real_end = NULL;
                }
        }
        //report_internal_mem_usage ();
@@ -2951,7 +3001,6 @@ search_fragment_for_size (size_t size)
                                nursery_fragments = frag->next;
                        nursery_next = frag->fragment_start;
                        nursery_frag_real_end = frag->fragment_end;
-                       nursery_temp_end = MIN (nursery_frag_real_end, nursery_next + size + SCAN_START_SIZE);
 
                        DEBUG (4, fprintf (gc_debug_file, "Using nursery fragment %p-%p, size: %zd (req: %zd)\n", nursery_next, nursery_frag_real_end, nursery_frag_real_end - nursery_next, size));
                        frag->next = fragment_freelist;
@@ -3002,17 +3051,20 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
 {
        /* FIXME: handle OOM */
        void **p;
+       char *new_next;
        int dummy;
+       gboolean res;
        size += ALLOC_ALIGN - 1;
        size &= ~(ALLOC_ALIGN - 1);
 
        g_assert (vtable->gc_descr);
-       LOCK_GC;
 
-       if (collect_before_allocs) {
+       if (G_UNLIKELY (collect_before_allocs)) {
                int dummy;
 
                if (nursery_section) {
+                       LOCK_GC;
+
                        update_current_thread_stack (&dummy);
                        stop_world ();
                        collect_nursery (0);
@@ -3021,62 +3073,132 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                                // FIXME:
                                g_assert_not_reached ();
                        }
+                       UNLOCK_GC;
                }
        }
 
-       p = (void**)nursery_next;
+       /* tlab_next and tlab_temp_end are TLS vars so accessing them might be expensive */
+
+       p = (void**)tlab_next;
        /* FIXME: handle overflow */
-       nursery_next += size;
-       if (nursery_next >= nursery_temp_end) {
-               /* there are two cases: the object is too big or we need to collect */
-               /* there can be another case (from ORP), if we cooperate with the runtime a bit:
-                * objects that need finalizers can have the high bit set in their size
-                * so the above check fails and we can readily add the object to the queue.
-                * This avoids taking again the GC lock when registering, but this is moot when
-                * doing thread-local allocation, so it may not be a good idea.
+       new_next = (char*)p + size;
+       tlab_next = new_next;
+
+       if (G_LIKELY (new_next < tlab_temp_end)) {
+               /* Fast path */
+
+               /* 
+                * FIXME: We might need a memory barrier here so the change to tlab_next is 
+                * visible before the vtable store.
                 */
-               if (size > MAX_SMALL_OBJ_SIZE) {
-                       /* get ready for possible collection */
-                       update_current_thread_stack (&dummy);
-                       nursery_next -= size;
-                       p = alloc_large_inner (vtable, size);
-               } else {
-                       if (nursery_next >= nursery_frag_real_end) {
-                               nursery_next -= size;
-                               /* when running in degraded mode, we continue allocing that way
-                                * for a while, to decrease the number of useless nursery collections.
-                                */
-                               if (degraded_mode && degraded_mode < DEFAULT_NURSERY_SIZE) {
-                                       p = alloc_degraded (vtable, size);
-                                       UNLOCK_GC;
-                                       return p;
-                               }
-                               if (!search_fragment_for_size (size)) {
-                                       /* get ready for possible collection */
-                                       update_current_thread_stack (&dummy);
-                                       minor_collect_or_expand_inner (size);
-                                       if (degraded_mode) {
-                                               p = alloc_degraded (vtable, size);
-                                               UNLOCK_GC;
-                                               return p;
+
+               DEBUG (6, fprintf (gc_debug_file, "Allocated object %p, vtable: %p (%s), size: %zd\n", p, vtable, vtable->klass->name, size));
+               *p = vtable;
+               
+               return p;
+       }
+
+       /* Slow path */
+
+       /* there are two cases: the object is too big or we run out of space in the TLAB */
+       /* we also reach here when the thread does its first allocation after a minor 
+        * collection, since the tlab_ variables are initialized to NULL.
+        * there can be another case (from ORP), if we cooperate with the runtime a bit:
+        * objects that need finalizers can have the high bit set in their size
+        * so the above check fails and we can readily add the object to the queue.
+        * This avoids taking again the GC lock when registering, but this is moot when
+        * doing thread-local allocation, so it may not be a good idea.
+        */
+       LOCK_GC;
+       if (size > MAX_SMALL_OBJ_SIZE) {
+               /* get ready for possible collection */
+               update_current_thread_stack (&dummy);
+               tlab_next -= size;
+               p = alloc_large_inner (vtable, size);
+       } else {
+               if (tlab_next >= tlab_real_end) {
+                       /* 
+                        * Run out of space in the TLAB. When this happens, some amount of space
+                        * remains in the TLAB, but not enough to satisfy the current allocation
+                        * request. Currently, we retire the TLAB in all cases, later we could
+                        * keep it if the remaining space is above a treshold, and satisfy the
+                        * allocation directly from the nursery.
+                        * FIXME: Currently, tlab_size < SCAN_START_SIZE, so scan_starts are not
+                        * set.
+                        */
+                       tlab_next -= size;
+                       /* when running in degraded mode, we continue allocing that way
+                        * for a while, to decrease the number of useless nursery collections.
+                        */
+                       if (degraded_mode && degraded_mode < DEFAULT_NURSERY_SIZE) {
+                               p = alloc_degraded (vtable, size);
+                               UNLOCK_GC;
+                               return p;
+                       }
+
+                       if (size > tlab_size) {
+                               /* Allocate directly from the nursery */
+                               if (nursery_next + size >= nursery_frag_real_end) {
+                                       if (!search_fragment_for_size (size)) {
+                                               /* get ready for possible collection */
+                                               update_current_thread_stack (&dummy);
+                                               minor_collect_or_expand_inner (size);
+                                               if (degraded_mode) {
+                                                       p = alloc_degraded (vtable, size);
+                                                       UNLOCK_GC;
+                                                       return p;
+                                               }
                                        }
                                }
-                               /* nursery_next changed by minor_collect_or_expand_inner () */
+
                                p = (void*)nursery_next;
                                nursery_next += size;
-                               if (nursery_next > nursery_temp_end) {
+                               if (nursery_next > nursery_frag_real_end) {
                                        // no space left
                                        g_assert (0);
                                }
                        } else {
-                               /* record the scan start so we can find pinned objects more easily */
+                               DEBUG (3, fprintf (gc_debug_file, "Retire TLAB: %p-%p [%ld]\n", tlab_start, tlab_real_end, (long)(tlab_real_end - tlab_next)));
+
+                               if (nursery_next + tlab_size >= nursery_frag_real_end) {
+                                       res = search_fragment_for_size (tlab_size);
+                                       if (!res) {
+                                               /* get ready for possible collection */
+                                               update_current_thread_stack (&dummy);
+                                               minor_collect_or_expand_inner (tlab_size);
+                                               if (degraded_mode) {
+                                                       p = alloc_degraded (vtable, size);
+                                                       UNLOCK_GC;
+                                                       return p;
+                                               }
+                                       }
+                               }
+
+                               /* Allocate a new TLAB from the current nursery fragment */
+                               tlab_start = nursery_next;
+                               nursery_next += tlab_size;
+                               tlab_next = tlab_start;
+                               tlab_real_end = tlab_start + tlab_size;
+                               tlab_temp_end = tlab_start + MIN (SCAN_START_SIZE, tlab_size);
+
+                               /* Allocate from the TLAB */
+                               p = (void*)tlab_next;
+                               tlab_next += size;
+                               g_assert (tlab_next <= tlab_real_end);
+
                                nursery_section->scan_starts [((char*)p - (char*)nursery_section->data)/SCAN_START_SIZE] = (char*)p;
-                               /* we just bump nursery_temp_end as well */
-                               nursery_temp_end = MIN (nursery_frag_real_end, nursery_next + SCAN_START_SIZE);
-                               DEBUG (5, fprintf (gc_debug_file, "Expanding local alloc: %p-%p\n", nursery_next, nursery_temp_end));
                        }
+               } else {
+                       /* Reached tlab_temp_end */
+
+                       /* record the scan start so we can find pinned objects more easily */
+                       nursery_section->scan_starts [((char*)p - (char*)nursery_section->data)/SCAN_START_SIZE] = (char*)p;
+                       /* we just bump tlab_temp_end as well */
+                       tlab_temp_end = MIN (tlab_real_end, tlab_next + SCAN_START_SIZE);
+                       DEBUG (5, fprintf (gc_debug_file, "Expanding local alloc: %p-%p\n", tlab_next, tlab_temp_end));
                }
        }
+
        DEBUG (6, fprintf (gc_debug_file, "Allocated object %p, vtable: %p (%s), size: %zd\n", p, vtable, vtable->klass->name, size));
        *p = vtable;
 
@@ -3555,6 +3677,10 @@ struct _SgenThreadInfo {
        int skip;
        void *stack_end;
        void *stack_start;
+       char **tlab_next_addr;
+       char **tlab_start_addr;
+       char **tlab_temp_end_addr;
+       char **tlab_real_end_addr;
        RememberedSet *remset;
 };
 
@@ -3916,6 +4042,45 @@ clear_remsets (void)
        }
 }
 
+/*
+ * Clear the thread local TLAB variables for all threads.
+ */
+static void
+clear_tlabs (void)
+{
+       SgenThreadInfo *info;
+       int i;
+
+       for (i = 0; i < THREAD_HASH_SIZE; ++i) {
+               for (info = thread_table [i]; info; info = info->next) {
+                       /* A new TLAB will be allocated when the thread does its first allocation */
+                       *info->tlab_start_addr = NULL;
+                       *info->tlab_next_addr = NULL;
+                       *info->tlab_temp_end_addr = NULL;
+                       *info->tlab_real_end_addr = NULL;
+               }
+       }
+}
+
+/*
+ * Find the tlab_next value of the TLAB which contains ADDR.
+ */
+static char*
+find_tlab_next_from_address (char *addr)
+{
+       SgenThreadInfo *info;
+       int i;
+
+       for (i = 0; i < THREAD_HASH_SIZE; ++i) {
+               for (info = thread_table [i]; info; info = info->next) {
+                       if (addr >= *info->tlab_start_addr && addr < *info->tlab_next_addr)
+                               return *info->tlab_next_addr;
+               }
+       }
+
+       return NULL;
+}
+
 /* LOCKING: assumes the GC lock is held */
 static SgenThreadInfo*
 gc_register_current_thread (void *addr)
@@ -3929,6 +4094,12 @@ gc_register_current_thread (void *addr)
        info->skip = 0;
        info->signal = 0;
        info->stack_start = NULL;
+       info->tlab_start_addr = &tlab_start;
+       info->tlab_next_addr = &tlab_next;
+       info->tlab_temp_end_addr = &tlab_temp_end;
+       info->tlab_real_end_addr = &tlab_real_end;
+
+       tlab_next_addr = &tlab_next;
 
        /* try to get it with attributes first */
 #if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK)
@@ -4750,22 +4921,184 @@ mono_gc_base_init (void)
        mono_gc_register_thread (&sinfo);
 }
 
+enum {
+       ATYPE_NORMAL,
+       ATYPE_NUM
+};
+
+/* FIXME: Do this in the JIT, where specialized allocation sequences can be created
+ * for each class. This is currently not easy to do, as it is hard to generate basic 
+ * blocks + branches, but it is easy with the linear IL codebase.
+ */
+static MonoMethod*
+create_allocator (int atype)
+{
+       int tlab_next_addr_offset = -1;
+       int tlab_temp_end_offset = -1;
+       int p_var, size_var, tlab_next_addr_var, new_next_var;
+       guint32 slowpath_branch;
+       MonoMethodBuilder *mb;
+       MonoMethod *res;
+       MonoMethodSignature *csig;
+       static gboolean registered = FALSE;
+
+       MONO_THREAD_VAR_OFFSET (tlab_next_addr, tlab_next_addr_offset);
+       MONO_THREAD_VAR_OFFSET (tlab_temp_end, tlab_temp_end_offset);
+
+       g_assert (tlab_next_addr_offset != -1);
+       g_assert (tlab_temp_end_offset != -1);
+
+       g_assert (atype == ATYPE_NORMAL);
+
+       if (!registered) {
+               mono_register_jit_icall (mono_gc_alloc_obj, "mono_gc_alloc_obj", mono_create_icall_signature ("object ptr int"), FALSE);
+               registered = TRUE;
+       }
+
+       csig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
+       csig->ret = &mono_defaults.object_class->byval_arg;
+       csig->params [0] = &mono_defaults.int_class->byval_arg;
+
+       mb = mono_mb_new (mono_defaults.object_class, "Alloc", MONO_WRAPPER_ALLOC);
+       size_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
+       /* size = vtable->klass->instance_size; */
+       mono_mb_emit_ldarg (mb, 0);
+       mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoClass, instance_size));
+       mono_mb_emit_byte (mb, CEE_ADD);
+       /* FIXME: assert instance_size stays a 4 byte integer */
+       mono_mb_emit_byte (mb, CEE_LDIND_U4);
+       mono_mb_emit_stloc (mb, size_var);
+
+       /* size += ALLOC_ALIGN - 1; */
+       mono_mb_emit_ldloc (mb, size_var);
+       mono_mb_emit_icon (mb, ALLOC_ALIGN - 1);
+       mono_mb_emit_byte (mb, CEE_ADD);
+       /* size &= ~(ALLOC_ALIGN - 1); */
+       mono_mb_emit_icon (mb, ~(ALLOC_ALIGN - 1));
+       mono_mb_emit_byte (mb, CEE_AND);
+       mono_mb_emit_stloc (mb, size_var);
+
+       /*
+        * We need to modify tlab_next, but the JIT only supports reading, so we read
+        * another tls var holding its address instead.
+        */
+
+       /* tlab_next_addr (local) = tlab_next_addr (TLS var) */
+       tlab_next_addr_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_TLS);
+       mono_mb_emit_i4 (mb, tlab_next_addr_offset);
+       mono_mb_emit_stloc (mb, tlab_next_addr_var);
+
+       /* p = (void**)tlab_next; */
+       p_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       mono_mb_emit_ldloc (mb, tlab_next_addr_var);
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       mono_mb_emit_stloc (mb, p_var);
+       
+       /* new_next = (char*)p + size; */
+       new_next_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       mono_mb_emit_ldloc (mb, p_var);
+       mono_mb_emit_ldloc (mb, size_var);
+       mono_mb_emit_byte (mb, CEE_CONV_I);
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_stloc (mb, new_next_var);
+
+       /* tlab_next = new_next */
+       mono_mb_emit_ldloc (mb, tlab_next_addr_var);
+       mono_mb_emit_ldloc (mb, new_next_var);
+       mono_mb_emit_byte (mb, CEE_STIND_I);
+
+       /* if (G_LIKELY (new_next < tlab_temp_end)) */
+       mono_mb_emit_ldloc (mb, new_next_var);
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_TLS);
+       mono_mb_emit_i4 (mb, tlab_temp_end_offset);
+       slowpath_branch = mono_mb_emit_short_branch (mb, MONO_CEE_BLT_UN_S);
+
+       /* Slowpath */
+
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
+
+       /* FIXME: mono_gc_alloc_obj takes a 'size_t' as an argument, not an int32 */
+       mono_mb_emit_ldarg (mb, 0);
+       mono_mb_emit_ldloc (mb, size_var);
+       mono_mb_emit_icall (mb, mono_gc_alloc_obj);
+       mono_mb_emit_byte (mb, CEE_RET);
+
+       /* Fastpath */
+       mono_mb_patch_short_branch (mb, slowpath_branch);
+
+       /* FIXME: Memory barrier */
+
+       /* *p = vtable; */
+       mono_mb_emit_ldloc (mb, p_var);
+       mono_mb_emit_ldarg (mb, 0);
+       mono_mb_emit_byte (mb, CEE_STIND_I);
+       
+       /* return p */
+       mono_mb_emit_ldloc (mb, p_var);
+       mono_mb_emit_byte (mb, CEE_RET);
+
+       res = mono_mb_create_method (mb, csig, 8);
+       mono_mb_free (mb);
+       mono_method_get_header (res)->init_locals = FALSE;
+       return res;
+}
+
+static MonoMethod* alloc_method_cache [ATYPE_NUM];
+
+/*
+ * Generate an allocator method implementing the fast path of mono_gc_alloc_obj ().
+ * The signature of the called method is:
+ *     object allocate (MonoVTable *vtable)
+ */
 MonoMethod*
 mono_gc_get_managed_allocator (MonoVTable *vtable, gboolean for_box)
 {
-       return NULL;
+       int tlab_next_offset = -1;
+       int tlab_temp_end_offset = -1;
+       MonoClass *klass = vtable->klass;
+       MONO_THREAD_VAR_OFFSET (tlab_next, tlab_next_offset);
+       MONO_THREAD_VAR_OFFSET (tlab_temp_end, tlab_temp_end_offset);
+
+       if (tlab_next_offset == -1 || tlab_temp_end_offset == -1)
+               return NULL;
+       if (klass->instance_size > tlab_size)
+               return NULL;
+       if (klass->has_finalize || klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
+               return NULL;
+       if (klass->rank)
+               return NULL;
+       if (klass->byval_arg.type == MONO_TYPE_STRING)
+               return NULL;
+       if (collect_before_allocs)
+               return NULL;
+
+       return mono_gc_get_managed_allocator_by_type (0);
 }
 
 int
 mono_gc_get_managed_allocator_type (MonoMethod *managed_alloc)
 {
-       return -1;
+       return 0;
 }
 
 MonoMethod*
 mono_gc_get_managed_allocator_by_type (int atype)
 {
-       return NULL;
+       MonoMethod *res;
+
+       mono_loader_lock ();
+       res = alloc_method_cache [atype];
+       if (!res)
+               res = alloc_method_cache [atype] = create_allocator (atype);
+       mono_loader_unlock ();
+       return res;
 }
 
 #endif /* HAVE_SGEN_GC */
index 9a9c087ee554e6f12050a9ab3999d416186bc53d..5453ee8e4fb564ea469cbb0779d096101d7691c5 100644 (file)
@@ -4331,6 +4331,12 @@ verify_clause_relationship (VerifyContext *ctx, MonoExceptionClause *clause, Mon
                ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clauses overlap"));
 }
 
+#define code_bounds_check(size) \
+       if (ip + size > end) {\
+               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Code overrun starting with 0x%x at 0x%04x", *ip, ctx.ip_offset)); \
+               break; \
+       } \
+
 /*
  * FIXME: need to distinguish between valid and verifiable.
  * Need to keep track of types on the stack.
@@ -4347,7 +4353,6 @@ mono_method_verify (MonoMethod *method, int level)
        MonoImage *image;
        VerifyContext ctx;
        GSList *tmp;
-
        VERIFIER_DEBUG ( printf ("Verify IL for method %s %s %s\n",  method->klass->name_space,  method->klass->name, method->name); );
 
        if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
@@ -4529,6 +4534,7 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_LDARG_S:
                case CEE_LDARGA_S:
+                       code_bounds_check (2);
                        push_arg (&ctx, ip [1],  *ip == CEE_LDARGA_S);
                        ip += 2;
                        break;
@@ -4615,11 +4621,13 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_STLOC_S:
+                       code_bounds_check (2);
                        store_local (&ctx, ip [1]);
                        ip += 2;
                        break;
 
                case CEE_STARG_S:
+                       code_bounds_check (2);
                        store_arg (&ctx, ip [1]);
                        ip += 2;
                        break;
@@ -4640,30 +4648,35 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_LDC_I4_S:
+                       code_bounds_check (2);
                        if (check_overflow (&ctx))
                                stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        ip += 2;
                        break;
 
                case CEE_LDC_I4:
+                       code_bounds_check (5);
                        if (check_overflow (&ctx))
                                stack_push_val (&ctx,TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        ip += 5;
                        break;
 
                case CEE_LDC_I8:
+                       code_bounds_check (9);
                        if (check_overflow (&ctx))
                                stack_push_val (&ctx,TYPE_I8, &mono_defaults.int64_class->byval_arg);
                        ip += 9;
                        break;
 
                case CEE_LDC_R4:
+                       code_bounds_check (5);
                        if (check_overflow (&ctx))
                                stack_push_val (&ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
                        ip += 5;
                        break;
 
                case CEE_LDC_R8:
+                       code_bounds_check (9);
                        if (check_overflow (&ctx))
                                stack_push_val (&ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
                        ip += 9;
@@ -4677,6 +4690,7 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_BEQ_S:
                case CEE_BNE_UN_S:
+                       code_bounds_check (2);
                        do_branch_op (&ctx, (signed char)ip [1] + 2, cmp_br_eq_op);
                        ip += 2;
                        need_merge = 1;
@@ -4690,6 +4704,7 @@ mono_method_verify (MonoMethod *method, int level)
                case CEE_BGT_UN_S:
                case CEE_BLE_UN_S:
                case CEE_BLT_UN_S:
+                       code_bounds_check (2);
                        do_branch_op (&ctx, (signed char)ip [1] + 2, cmp_br_op);
                        ip += 2;
                        need_merge = 1;
@@ -4697,6 +4712,7 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_BEQ:
                case CEE_BNE_UN:
+                       code_bounds_check (5);
                        do_branch_op (&ctx, (gint32)read32 (ip + 1) + 5, cmp_br_eq_op);
                        ip += 5;
                        need_merge = 1;
@@ -4710,6 +4726,7 @@ mono_method_verify (MonoMethod *method, int level)
                case CEE_BGT_UN:
                case CEE_BLE_UN:
                case CEE_BLT_UN:
+                       code_bounds_check (5);
                        do_branch_op (&ctx, (gint32)read32 (ip + 1) + 5, cmp_br_op);
                        ip += 5;
                        need_merge = 1;
@@ -4717,6 +4734,7 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_LDLOC_S:
                case CEE_LDLOCA_S:
+                       code_bounds_check (2);
                        push_local (&ctx, ip[1], *ip == CEE_LDLOCA_S);
                        ip += 2;
                        break;
@@ -4739,6 +4757,7 @@ mono_method_verify (MonoMethod *method, int level)
                }
 
                case CEE_JMP:
+                       code_bounds_check (5);
                        if (ctx.eval.size)
                                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Eval stack must be empty in jmp at 0x%04x", ip_offset));
                        token = read32 (ip + 1);
@@ -4753,11 +4772,13 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
                case CEE_CALL:
                case CEE_CALLVIRT:
+                       code_bounds_check (5);
                        do_invoke_method (&ctx, read32 (ip + 1), *ip == CEE_CALLVIRT);
                        ip += 5;
                        break;
 
                case CEE_CALLI:
+                       code_bounds_check (5);
                        token = read32 (ip + 1);
                        /*
                         * FIXME: check signature, retval, arguments etc.
@@ -4767,6 +4788,7 @@ mono_method_verify (MonoMethod *method, int level)
                        ip += 5;
                        break;
                case CEE_BR_S:
+                       code_bounds_check (2);
                        do_static_branch (&ctx, (signed char)ip [1] + 2);
                        need_merge = 1;
                        ip += 2;
@@ -4775,12 +4797,14 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_BRFALSE_S:
                case CEE_BRTRUE_S:
+                       code_bounds_check (2);
                        do_boolean_branch_op (&ctx, (signed char)ip [1] + 2);
                        ip += 2;
                        need_merge = 1;
                        break;
 
                case CEE_BR:
+                       code_bounds_check (5);
                        do_static_branch (&ctx, (gint32)read32 (ip + 1) + 5);
                        need_merge = 1;
                        ip += 5;
@@ -4789,13 +4813,17 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_BRFALSE:
                case CEE_BRTRUE:
+                       code_bounds_check (5);
                        do_boolean_branch_op (&ctx, (gint32)read32 (ip + 1) + 5);
                        ip += 5;
                        need_merge = 1;
                        break;
 
                case CEE_SWITCH:
+                       code_bounds_check (5);
                        n = read32 (ip + 1);
+                       code_bounds_check (5 + sizeof (guint32) * n);
+                       
                        do_switch (&ctx, n, (ip + 5));
                        start = 1;
                        ip += 5 + sizeof (guint32) * n;
@@ -4864,27 +4892,32 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_CPOBJ:
+                       code_bounds_check (5);
                        do_cpobj (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_LDOBJ:
+                       code_bounds_check (5);
                        do_ldobj_value (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_LDSTR:
+                       code_bounds_check (5);
                        do_ldstr (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_NEWOBJ:
+                       code_bounds_check (5);
                        do_newobj (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_CASTCLASS:
                case CEE_ISINST:
+                       code_bounds_check (5);
                        do_cast (&ctx, read32 (ip + 1), *ip == CEE_CASTCLASS ? "castclass" : "isinst");
                        ip += 5;
                        break;
@@ -4893,7 +4926,9 @@ mono_method_verify (MonoMethod *method, int level)
                case CEE_UNUSED1:
                        ++ip; /* warn, error ? */
                        break;
+
                case CEE_UNBOX:
+                       code_bounds_check (5);
                        do_unbox_value (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -4906,27 +4941,32 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_LDFLD:
                case CEE_LDFLDA:
+                       code_bounds_check (5);
                        do_push_field (&ctx, read32 (ip + 1), *ip == CEE_LDFLDA);
                        ip += 5;
                        break;
 
                case CEE_LDSFLD:
                case CEE_LDSFLDA:
+                       code_bounds_check (5);
                        do_push_static_field (&ctx, read32 (ip + 1), *ip == CEE_LDSFLDA);
                        ip += 5;
                        break;
 
                case CEE_STFLD:
+                       code_bounds_check (5);
                        do_store_field (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_STSFLD:
+                       code_bounds_check (5);
                        do_store_static_field (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_STOBJ:
+                       code_bounds_check (5);
                        do_stobj (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -4954,11 +4994,13 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_BOX:
+                       code_bounds_check (5);
                        do_box_value (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_NEWARR:
+                       code_bounds_check (5);
                        do_newarr (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -4969,6 +5011,7 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_LDELEMA:
+                       code_bounds_check (5);
                        do_ldelema (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -5001,16 +5044,19 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_LDELEM_ANY:
+                       code_bounds_check (5);
                        do_ldelem (&ctx, *ip, read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_STELEM_ANY:
+                       code_bounds_check (5);
                        do_stelem (&ctx, *ip, read32 (ip + 1));
                        ip += 5;
                        break;
                        
                case CEE_UNBOX_ANY:
+                       code_bounds_check (5);
                        do_unbox_any (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -5038,6 +5084,7 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_REFANYVAL:
+                       code_bounds_check (5);
                        do_refanyval (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -5048,11 +5095,13 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_MKREFANY:
+                       code_bounds_check (5);
                        do_mkrefany (&ctx,  read32 (ip + 1));
                        ip += 5;
                        break;
 
                case CEE_LDTOKEN:
+                       code_bounds_check (5);
                        do_load_token (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
@@ -5066,21 +5115,25 @@ mono_method_verify (MonoMethod *method, int level)
                        break;
 
                case CEE_LEAVE:
+                       code_bounds_check (5);
                        do_leave (&ctx, read32 (ip + 1) + 5);
                        ip += 5;
                        start = 1;
                        break;
 
                case CEE_LEAVE_S:
+                       code_bounds_check (2);
                        do_leave (&ctx, (signed char)ip [1] + 2);
                        ip += 2;
                        start = 1;
                        break;
 
                case CEE_PREFIX1:
+                       code_bounds_check (2);
                        ++ip;
                        switch (*ip) {
                        case CEE_STLOC:
+                               code_bounds_check (3);
                                store_local (&ctx, read16 (ip + 1));
                                ip += 3;
                                break;
@@ -5099,6 +5152,7 @@ mono_method_verify (MonoMethod *method, int level)
                                break;
 
                        case CEE_STARG:
+                               code_bounds_check (3);
                                store_arg (&ctx, read16 (ip + 1) );
                                ip += 3;
                                break;
@@ -5113,11 +5167,13 @@ mono_method_verify (MonoMethod *method, int level)
                                break;
        
                        case CEE_LDFTN:
+                               code_bounds_check (5);
                                do_load_function_ptr (&ctx, read32 (ip + 1), FALSE);
                                ip += 5;
                                break;
 
                        case CEE_LDVIRTFTN:
+                               code_bounds_check (5);
                                do_load_function_ptr (&ctx, read32 (ip + 1), TRUE);
                                ip += 5;
                                break;
@@ -5128,12 +5184,14 @@ mono_method_verify (MonoMethod *method, int level)
 
                        case CEE_LDARG:
                        case CEE_LDARGA:
+                               code_bounds_check (3);
                                push_arg (&ctx, read16 (ip + 1),  *ip == CEE_LDARGA);
                                ip += 3;
                                break;
 
                        case CEE_LDLOC:
                        case CEE_LDLOCA:
+                               code_bounds_check (3);
                                push_local (&ctx, read16 (ip + 1), *ip == CEE_LDLOCA);
                                ip += 3;
                                break;
@@ -5152,6 +5210,7 @@ mono_method_verify (MonoMethod *method, int level)
                                ++ip;
                                break;
                        case CEE_UNALIGNED_:
+                               code_bounds_check (2);
                                prefix |= PREFIX_UNALIGNED;
                                ip += 2;
                                break;
@@ -5167,11 +5226,13 @@ mono_method_verify (MonoMethod *method, int level)
                                break;
 
                        case CEE_INITOBJ:
+                               code_bounds_check (5);
                                do_initobj (&ctx, read32 (ip + 1));
                                ip += 5;
                                break;
 
                        case CEE_CONSTRAINED_:
+                               code_bounds_check (5);
                                ctx.constrained_type = get_boxable_mono_type (&ctx, read32 (ip + 1), "constrained.");
                                prefix |= PREFIX_CONSTRAINED;
                                ip += 5;
@@ -5212,6 +5273,7 @@ mono_method_verify (MonoMethod *method, int level)
                                break;
 
                        case CEE_SIZEOF:
+                               code_bounds_check (5);
                                do_sizeof (&ctx, read32 (ip + 1));
                                ip += 5;
                                break;
diff --git a/mono/tests/verifier/BatchCompiler.cs b/mono/tests/verifier/BatchCompiler.cs
new file mode 100644 (file)
index 0000000..b8d0679
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// AssemblyRunner.cs
+//
+// Author:
+//   Rodrigo Kumpera (rkumpera@novell.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Reflection;
+
+
+namespace Verifier {
+       public class BatchCompiler : MarshalByRefObject {
+               static BatchCompiler NewBatchCompiler () {
+                       AppDomain domain = AppDomain.CreateDomain ("test");
+                       BatchCompiler compiler = (BatchCompiler) domain.CreateInstanceAndUnwrap(
+                               Assembly.GetExecutingAssembly().FullName,
+                               "Verifier.BatchCompiler");
+                       return compiler;
+               }
+
+               public static void Main (String[] args) {
+                       int total = 0;
+                       BatchCompiler bc = NewBatchCompiler ();
+
+                       foreach (string src in Directory.GetFiles (".", "*.il")) {
+                               if (!bc.Compile (src)) 
+                                       bc = NewBatchCompiler ();
+                               else
+                                       ++total;
+                       }
+                       Console.WriteLine ("Total compiled successfully {0}", total);
+               }
+
+               public bool Compile (String src) {
+                       try {
+                               Mono.ILASM.Driver.Main (new string[] { src });
+                               string binary = src.Substring (0, src.Length - 3) + ".exe";
+                               return File.Exists (binary);
+                       } catch (Exception e) {
+                               Console.WriteLine ("Error compiling {0}", e);
+                               return false;
+                       }
+               }
+       }
+}
+
index c14c1f59cf745f2764ea93d200abaf364f57393c..fcd0023ee2335811e71095d96fdd03b7e723c5b8 100644 (file)
@@ -1,3 +1,21 @@
+2008-05-01 Rodrigo Kumpera <rkumpera@novell.com>
+
+       * unverifiable_ldsfld_no_fld.il: Fixed compilation
+       and renamed to invalid_ldsfld_no_fld.il.
+
+       * BatchCompiler.cs: New driver to fast compile the
+       verifier test suite. It's about 20x faster now.
+
+       * Makefile: Use the ilasm driver for faster compilation.
+
+2008-04-30 Rodrigo Kumpera <rkumpera@novell.com>
+
+       * make_il_overflow_test.sh: New test generator
+       for a truncated IL stream.
+
+       * make_tests.sh: Fixed generation script. Added
+       tests using the new generator.
+
 2008-04-23 Rodrigo Kumpera <rkumpera@novell.com>
 
        * make_tests.sh: Add some tests for overlapping
index e208f1856dc9527203f5fcbc37af2d955495a7df..fcfa0a82441368335bbc2d24c9a2758e6d34296c 100644 (file)
@@ -1,10 +1,18 @@
 
 %.exe: %.cil
-       ilasm -out:$@ $<
+       ilasm2 -out:$@ $<
 
-compile-stamp: generate-stamp
-       for i in *.il; do ilasm2 $$i; done
-       for i in *.cs; do gmcs /unsafe $$i; done
+BatchCompiler.exe: BatchCompiler.cs
+       gmcs -r:../../../../mcs/class/lib/net_2_0/ilasm.exe BatchCompiler.cs
+
+compile-stamp: generate-stamp BatchCompiler.exe
+       for i in *.cs; do \
+               EXE="`echo $$i | cut -d. -f1`.exe"; \
+               if ! [ -f $$EXE ]; then \
+                       gmcs /unsafe $$i; \
+               fi \
+       done 
+       MONO_PATH=../../../../mcs/class/lib/net_2_0/ mono BatchCompiler.exe
        touch compile-stamp
 
 clean:
@@ -20,7 +28,7 @@ generate-stamp: make_tests.sh make_bin_test.sh make_exception_branch_test.sh mak
 
 test: compile-stamp run-test
 
-run-test:
+run-test: compile-stamp
        @for i in *.exe; do \
                TEST=`echo $$i | cut -d '.' -f 1`; \
                RES=99; \
@@ -29,7 +37,7 @@ run-test:
                then \
                        RES=3; \
                fi; \
-               if [ "$$FIRST" == "unverifiable" ]; \
+               if [ "$$FIRST" == "unverifiable" ] || [ "$FIRST" == "typeunverifiable" ]; \
                then \
                        RES=2; \
                fi; \
@@ -64,7 +72,7 @@ run-test:
                        if [ $$R2 != 0 ]; then \
                                echo "$$TEST is type unverifiable but did not pass under non-strict check, got $${R2} but expected 0"; \
                        fi \
-               else \
+               elif [ $RES != 99 ]; then \
                        ../../metadata/pedump --verify error,warn,cls,code $$TEST.exe >/dev/null 2>/dev/null; \
                        R=$$?; \
                        if [ $$R != $$RES ]; then \
diff --git a/mono/tests/verifier/invalid_ldsfld_no_fld.il b/mono/tests/verifier/invalid_ldsfld_no_fld.il
new file mode 100644 (file)
index 0000000..7007ac9
--- /dev/null
@@ -0,0 +1,29 @@
+// Invalid CIL which breaks the ECMA-335,III,4.14 rules. 
+// This CIL should fail verification by a conforming CLI verifier.
+
+.assembly 'test_generated'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+
+
+.class public auto ansi beforefieldinit c
+       extends [mscorlib]System.Object
+{
+}
+
+.method public static int32 Main() cil managed
+{
+       .entrypoint
+       .maxstack 2
+       .locals init (
+               class c V_0
+       )
+       ldloc.0
+       ldsfld int32 c::invalid // Invalid, no field invalid in class c.
+       pop
+       ldc.i4.0
+       ret
+}
+
diff --git a/mono/tests/verifier/make_il_overflow_test.sh b/mono/tests/verifier/make_il_overflow_test.sh
new file mode 100755 (executable)
index 0000000..5e42052
--- /dev/null
@@ -0,0 +1,62 @@
+#! /bin/sh
+
+TEST_NAME=$1
+TEST_VALIDITY=$2
+TEST_BYTE_0=$3
+TEST_BYTE_1=$4
+TEST_BYTE_2=$5
+TEST_BYTE_3=$6
+TEST_BYTE_4=$7
+
+
+if [ "$TEST_BYTE_1" != "" ] ; then
+       EMIT_BYTE_1=".emitbyte $TEST_BYTE_1";
+fi
+
+if [ "$TEST_BYTE_2" != "" ] ; then
+       EMIT_BYTE_2=".emitbyte $TEST_BYTE_2";
+fi
+
+if [ "$TEST_BYTE_3" != "" ] ; then
+       EMIT_BYTE_3=".emitbyte $TEST_BYTE_3";
+fi
+
+if [ "$TEST_BYTE_4" != "" ] ; then
+       EMIT_BYTE_4=".emitbyte $TEST_BYTE_4";
+fi
+
+if [ "$TEST_BYTE_5" != "" ] ; then
+       EMIT_BYTE_5=".emitbyte $TEST_BYTE_5";
+fi
+
+TEST_FILE=`echo ${TEST_VALIDITY}_${TEST_NAME} | sed -e 's/ /_/g' -e 's/\./_/g' -e 's/&/mp/g' -e 's/\[/_/g' -e 's/\]/_/g'`_generated.il
+echo $TEST_FILE
+sed -e "s/VALIDITY/${TEST_VALIDITY}/g" -e "s/BYTE_0/${TEST_BYTE_0}/g" -e "s/BYTE_1/${TEST_BYTE_1}/g" > $TEST_FILE <<//EOF
+
+// VALIDITY CIL which breaks the ECMA-335 rules. 
+// this CIL should fail verification by a conforming CLI verifier.
+
+.assembly '${TEST_NAME}_generated'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+
+.method public static void Main() cil managed
+{
+       .entrypoint
+       .maxstack 2
+       .locals init ()
+
+       nop
+       nop
+       .emitbyte BYTE_0
+       ${EMIT_BYTE_1}
+       ${EMIT_BYTE_2}
+       ${EMIT_BYTE_3}
+       ${EMIT_BYTE_4}
+       ${EMIT_BYTE_5}
+}
+
+
+//EOF
index 4ad14bd9200c060f45ea8c2a20f5fbebb0e0ed19..679a265aed414a143744f7f913caf039a7bfcdcd 100755 (executable)
@@ -189,6 +189,7 @@ do
        ./make_bin_test.sh bin_cgt_un_a_${I} unverifiable 'cgt.un' "${TYPE}" 'object'
        ./make_bin_test.sh bin_cgt_un_b_${I} unverifiable 'cgt.un' 'object' "${TYPE}"
   I=`expr $I + 1`
+done
 
 for OP in ceq
 do
@@ -4977,5 +4978,38 @@ done
 
 
 
+#test for IL overflow
+
+for I in 0x0E 0x0F 0x10 0x11 0x12 0x13 0x1F 0x2B 0x2C 0x2D 0x2E 0x2F 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0xDE 0xFE
+do
+       ./make_il_overflow_test.sh incomplete_op_${I} invalid $I
+done
+
+for I in 0x20 0x21 0x22 0x23 0x28 0x29 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F 0x40 0x41 0x42 0x43 0x44 0x6F 0x70 0x71 0x72 0x73 0x74 0x75 0x79 0x7B 0x7C 0x7D 0x7E 0x7F 0x80 0x81 0x8D 0x8C 0x8F 0xA3 0xA4 0xA5 0xC2 0xC6 0xD0 0xDD
+do
+       ./make_il_overflow_test.sh incomplete_op_${I} invalid $I
+       ./make_il_overflow_test.sh incomplete_op_${I}_0x00 invalid $I 0x00
+       ./make_il_overflow_test.sh incomplete_op_${I}_0x00_0x00 invalid $I 0x00 0x00
+       ./make_il_overflow_test.sh incomplete_op_${I}_0x00_0x00_0x00 invalid $I 0x00 0x00
+done
+
+
+for I in 0x06 0x07 0x09 0x0A 0x0E 0x0B 0x0C 0x0D 0x12 0x15 0x16 0x19 0x1C
+do
+       ./make_il_overflow_test.sh incomplete_op_0xFE_${I} invalid 0xFE $I
+       ./make_il_overflow_test.sh incomplete_op_0xFE_${I}_0x00 invalid 0xFE $I 0x00
+done
+
+#switch
+./make_il_overflow_test.sh incomplete_switch_1 invalid 0x45
+./make_il_overflow_test.sh incomplete_switch_2 invalid 0x45 0x00
+./make_il_overflow_test.sh incomplete_switch_3 invalid 0x45 0x00 0x00
+./make_il_overflow_test.sh incomplete_switch_4 invalid 0x45 0x00 0x00
+
+./make_il_overflow_test.sh incomplete_switch_arg_1 invalid 0x45 0x00 0x00 0x00 0x01
+./make_il_overflow_test.sh incomplete_switch_arg_2 invalid 0x45 0x00 0x00 0x00 0x01 0x00
+
+
+
 
 
diff --git a/mono/tests/verifier/unverifiable_ldsfld_no_fld.il b/mono/tests/verifier/unverifiable_ldsfld_no_fld.il
deleted file mode 100644 (file)
index e89ede2..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// Invalid CIL which breaks the ECMA-335,III,4.14 rules. 
-// This CIL should fail verification by a conforming CLI verifier.
-
-.assembly 'test_generated'
-{
-  .hash algorithm 0x00008004
-  .ver  0:0:0:0
-}
-
-
-.class public auto ansi beforefieldinit c
-       extends [mscorlib]System.Object
-{
-}
-
-.method public static int32 Main() cil managed
-{
-       .entrypoint
-       .maxstack 2
-       .locals init (
-               class c V_0
-       )
-       ldloc.0
-       ldsfld int32 c::invalid // Invalid, no field invalid in class c.
-       pop
-       ldc.i4.0
-       ret
-}
-// Invalid CIL which breaks the ECMA-335,III,4.14 rules. 
-// This CIL should fail verification by a conforming CLI verifier.
-
-.assembly 'test_generated'
-{
-  .hash algorithm 0x00008004
-  .ver  0:0:0:0
-}
-
-
-.class public auto ansi beforefieldinit c
-       extends [mscorlib]System.Object
-{
-}
-
-.method public static int32 Main() cil managed
-{
-       .entrypoint
-       .maxstack 2
-       .locals init (
-               class c V_0
-       )
-       ldloc.0
-       ldsfld int32 c::invalid // Invalid, no field invalid in class c.
-       pop
-       ldc.i4.0
-       ret
-}