Merge pull request #5668 from kumpera/wasm-work-p4
authorRodrigo Kumpera <kumpera@users.noreply.github.com>
Mon, 2 Oct 2017 23:36:39 +0000 (16:36 -0700)
committerGitHub <noreply@github.com>
Mon, 2 Oct 2017 23:36:39 +0000 (16:36 -0700)
More WASM fixes.

92 files changed:
external/api-snapshot
external/nuget-buildtasks
mcs/class/System.Drawing/System.Drawing.Drawing2D/LinearGradientBrush.cs
mcs/class/System.Drawing/Test/System.Drawing.Drawing2D/LinearGradientBrushTest.cs
mcs/class/System.Drawing/Test/System.Drawing/GDIPlusTest.cs
mcs/class/System.Json/System.Json/JsonArray.cs
mcs/class/System.Json/Test/System.Json/JsonValueTest.cs
mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs
mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs
mcs/errors/cs0131-6.cs [new file with mode: 0644]
mcs/errors/cs0199-2.cs [new file with mode: 0644]
mcs/errors/cs0206-5.cs [new file with mode: 0644]
mcs/errors/cs1503-17.cs [new file with mode: 0644]
mcs/errors/cs1547-13.cs [new file with mode: 0644]
mcs/errors/cs1644-55.cs [new file with mode: 0644]
mcs/errors/cs1715-3.cs [new file with mode: 0644]
mcs/errors/cs1764.cs
mcs/errors/cs8145.cs [new file with mode: 0644]
mcs/errors/cs8146.cs [new file with mode: 0644]
mcs/errors/cs8147-2.cs [new file with mode: 0644]
mcs/errors/cs8147.cs [new file with mode: 0644]
mcs/errors/cs8148-2.cs [new file with mode: 0644]
mcs/errors/cs8148.cs [new file with mode: 0644]
mcs/errors/cs8149-2.cs [new file with mode: 0644]
mcs/errors/cs8149.cs [new file with mode: 0644]
mcs/errors/cs8150.cs [new file with mode: 0644]
mcs/errors/cs8151.cs [new file with mode: 0644]
mcs/errors/cs8152.cs [new file with mode: 0644]
mcs/errors/cs8153.cs [new file with mode: 0644]
mcs/errors/cs8154.cs [new file with mode: 0644]
mcs/errors/cs8155.cs [new file with mode: 0644]
mcs/errors/cs8156-2.cs [new file with mode: 0644]
mcs/errors/cs8156.cs [new file with mode: 0644]
mcs/errors/cs8157.cs [new file with mode: 0644]
mcs/errors/cs8160.cs [new file with mode: 0644]
mcs/errors/cs8161.cs [new file with mode: 0644]
mcs/errors/cs8170-2.cs [new file with mode: 0644]
mcs/errors/cs8170.cs [new file with mode: 0644]
mcs/errors/cs8171.cs [new file with mode: 0644]
mcs/errors/cs8172.cs [new file with mode: 0644]
mcs/errors/cs8173.cs [new file with mode: 0644]
mcs/errors/cs8174.cs [new file with mode: 0644]
mcs/errors/cs8175.cs [new file with mode: 0644]
mcs/errors/cs8176.cs [new file with mode: 0644]
mcs/errors/cs8177.cs [new file with mode: 0644]
mcs/errors/cs8178-2.cs [new file with mode: 0644]
mcs/errors/cs8178.cs [new file with mode: 0644]
mcs/errors/cs8189.cs [new file with mode: 0644]
mcs/errors/known-issues-net_4_x
mcs/mcs/argument.cs
mcs/mcs/class.cs
mcs/mcs/convert.cs
mcs/mcs/cs-parser.jay
mcs/mcs/delegate.cs
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/generic.cs
mcs/mcs/iterators.cs
mcs/mcs/lambda.cs
mcs/mcs/membercache.cs
mcs/mcs/pending.cs
mcs/mcs/property.cs
mcs/mcs/statement.cs
mcs/mcs/typespec.cs
mcs/tests/test-ref-01.cs [new file with mode: 0644]
mcs/tests/test-ref-02.cs [new file with mode: 0644]
mcs/tests/test-ref-03.cs [new file with mode: 0644]
mcs/tests/test-ref-04.cs [new file with mode: 0644]
mcs/tests/test-ref-05.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml
mono/btls/Makefile.am
mono/metadata/Makefile.am
mono/metadata/callspec.c [new file with mode: 0644]
mono/metadata/callspec.h [new file with mode: 0644]
mono/metadata/class.c
mono/mini/driver.c
mono/mini/iltests.il
mono/mini/method-to-ir.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/trace.c
mono/mini/trace.h
mono/profiler/log-args.c
mono/profiler/log.c
mono/profiler/log.h
mono/tests/array.cs
msvc/libmonoruntime.vcxproj
packaging/MacSDK/profile.py
packaging/MacSDKRelease/mono-extensions.py
scripts/ci/collect-coverage.sh
scripts/ci/run-jenkins.sh

index 090c95d755f8112db5cf6c30df92a9941d9124a4..627333cae84f02a36ee9ca605c96dac4557d9f35 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 090c95d755f8112db5cf6c30df92a9941d9124a4
+Subproject commit 627333cae84f02a36ee9ca605c96dac4557d9f35
index 9e04cc7f41899c880807d1d055a24c768670784a..b58ba4282377bcefd48abdc2d62ce6330e079abe 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9e04cc7f41899c880807d1d055a24c768670784a
+Subproject commit b58ba4282377bcefd48abdc2d62ce6330e079abe
index 3b006fd5c9684a4356f5ef5808b6683e39655277..d2e645d2ccbd23152f27b54043cf6ad60308cdd5 100644 (file)
@@ -67,6 +67,14 @@ namespace System.Drawing.Drawing2D {
 
                public LinearGradientBrush (Rectangle rect, Color color1, Color color2, LinearGradientMode linearGradientMode)
                {
+                       if (linearGradientMode < LinearGradientMode.Horizontal || linearGradientMode > LinearGradientMode.BackwardDiagonal) {
+                               throw new InvalidEnumArgumentException (nameof (linearGradientMode), unchecked ((int)linearGradientMode), typeof (LinearGradientMode));
+                       }
+
+                       if (rect.Width == 0 || rect.Height == 0) {
+                               throw new ArgumentException( string.Format ("Rectangle '{0}' cannot have a width or height equal to 0.", rect.ToString ()));
+                       }
+
                        IntPtr nativeObject;
                        Status status = GDIPlus.GdipCreateLineBrushFromRectI (ref rect, color1.ToArgb (), color2.ToArgb (), linearGradientMode, WrapMode.Tile, out nativeObject);
                        GDIPlus.CheckStatus (status);
@@ -81,6 +89,14 @@ namespace System.Drawing.Drawing2D {
 
                public LinearGradientBrush (RectangleF rect, Color color1, Color color2, LinearGradientMode linearGradientMode)
                {
+                       if (linearGradientMode < LinearGradientMode.Horizontal || linearGradientMode > LinearGradientMode.BackwardDiagonal) {
+                               throw new InvalidEnumArgumentException (nameof (linearGradientMode), unchecked ((int)linearGradientMode), typeof (LinearGradientMode));
+                       }
+
+                       if (rect.Width == 0.0 || rect.Height == 0.0) {
+                               throw new ArgumentException (string.Format ("Rectangle '{0}' cannot have a width or height equal to 0.", rect.ToString ()));
+                       }
+
                        IntPtr nativeObject;
                        Status status = GDIPlus.GdipCreateLineBrushFromRect (ref rect, color1.ToArgb (), color2.ToArgb (), linearGradientMode, WrapMode.Tile, out nativeObject);
                        GDIPlus.CheckStatus (status);
@@ -95,6 +111,10 @@ namespace System.Drawing.Drawing2D {
 
                public LinearGradientBrush (Rectangle rect, Color color1, Color color2, float angle, bool isAngleScaleable)
                {
+                       if (rect.Width == 0 || rect.Height == 0) {
+                               throw new ArgumentException (string.Format ("Rectangle '{0}' cannot have a width or height equal to 0.", rect.ToString ()));
+                       }
+
                        IntPtr nativeObject;
                        Status status = GDIPlus.GdipCreateLineBrushFromRectWithAngleI (ref rect, color1.ToArgb (), color2.ToArgb (), angle, isAngleScaleable, WrapMode.Tile, out nativeObject);
                        GDIPlus.CheckStatus (status);
@@ -105,6 +125,10 @@ namespace System.Drawing.Drawing2D {
 
                public LinearGradientBrush (RectangleF rect, Color color1, Color color2, float angle, bool isAngleScaleable)
                {
+                       if (rect.Width == 0 || rect.Height == 0) {
+                               throw new ArgumentException (string.Format ("Rectangle '{0}' cannot have a width or height equal to 0.", rect.ToString ()));
+                       }
+
                        IntPtr nativeObject;
                        Status status = GDIPlus.GdipCreateLineBrushFromRectWithAngle (ref rect, color1.ToArgb (), color2.ToArgb (), angle, isAngleScaleable, WrapMode.Tile, out nativeObject);
                        GDIPlus.CheckStatus (status);
index 937c9ebbc792cae616e995b0e53c62cfb8248d3d..ebf1f86e98c011afcb83248fff95483c59b9ce40 100644 (file)
@@ -324,6 +324,42 @@ namespace MonoTests.System.Drawing.Drawing2D {
                        Assert.AreEqual (32, elements[5], 0.0001, "matrix.5");
                }
 
+               [Test]
+               public void Constructor_Rectangle_InvalidWidthHeight ()
+               {
+                       var emptyWidth = new Rectangle (0, 0, 0, 1);
+                       var emptyHeight = new Rectangle (0, 0, 0, 1);
+
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyWidth, Color.Empty, Color.Empty, 1));
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyHeight, Color.Empty, Color.Empty, 1));
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyWidth, Color.Empty, Color.Empty, LinearGradientMode.BackwardDiagonal));
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyHeight, Color.Empty, Color.Empty, LinearGradientMode.BackwardDiagonal));
+               }
+
+               [Test]
+               public void Constructor_RectangleF_InvalidWidthHeight ()
+               {
+                       var emptyWidth = new RectangleF (0, 0, 0, 1);
+                       var emptyHeight = new RectangleF (0, 0, 0, 1);
+
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyWidth, Color.Empty, Color.Empty, 1));
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyHeight, Color.Empty, Color.Empty, 1));
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyWidth, Color.Empty, Color.Empty, LinearGradientMode.BackwardDiagonal));
+                       Assert.Throws<ArgumentException>(() => new LinearGradientBrush (emptyHeight, Color.Empty, Color.Empty, LinearGradientMode.BackwardDiagonal));
+               }
+
+               [Test]
+               public void Constructor_LinearGradientMode_InvalidMode ()
+               {
+                       var rect = new Rectangle (0, 0, 1, 1);
+                       var rectf = new RectangleF (0, 0, 1, 1);
+
+                       Assert.Throws<InvalidEnumArgumentException>(() => new LinearGradientBrush (rect, Color.Empty, Color.Empty, LinearGradientMode.Horizontal - 1));
+                       Assert.Throws<InvalidEnumArgumentException>(() => new LinearGradientBrush (rectf, Color.Empty, Color.Empty, LinearGradientMode.Horizontal - 1));
+                       Assert.Throws<InvalidEnumArgumentException>(() => new LinearGradientBrush (rect, Color.Empty, Color.Empty, LinearGradientMode.BackwardDiagonal + 1));
+                       Assert.Throws<InvalidEnumArgumentException>(() => new LinearGradientBrush (rectf, Color.Empty, Color.Empty, LinearGradientMode.BackwardDiagonal + 1));
+               }
+
                [Test]
                public void InterpolationColors_Colors_InvalidBlend ()
                {
index 958aa0bb31907f87a009abc73daa667031716b1e..4e6c25725298c8f808a2ac4720fcbd63a8c4dece 100644 (file)
@@ -864,14 +864,6 @@ namespace MonoTests.System.Drawing {
                                        Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipSetImagePalette (IntPtr.Zero, palette), "GdipSetImagePalette(null,palette)");
                                        Assert.AreEqual (Status.InvalidParameter, GDIPlus.GdipSetImagePalette (bitmap, IntPtr.Zero), "GdipSetImagePalette(bitmap,null)");
                                        Assert.AreEqual (Status.Ok, GDIPlus.GdipSetImagePalette (bitmap, palette), "GdipSetImagePalette");
-
-                                       // change palette to 0 entries
-                                       int flags = Marshal.ReadInt32 (palette);
-                                       Marshal.WriteInt64 (palette, flags << 32);
-                                       Assert.AreEqual (Status.Ok, GDIPlus.GdipSetImagePalette (bitmap, palette), "GdipSetImagePalette/Empty");
-
-                                       Assert.AreEqual (Status.Ok, GDIPlus.GdipGetImagePaletteSize (bitmap, out size), "GdipGetImagePaletteSize/Empty");
-                                       Assert.AreEqual (8, size, "size");
                                }
                                finally {
                                        Marshal.FreeHGlobal (palette);
index c63004422b5b4919cd665c7adc08144b1aee53e8..524e3e8b75007c0163ca85dce45f1bf4c003b4cb 100644 (file)
@@ -45,9 +45,6 @@ namespace System.Json
 
                public void Add (JsonValue item)
                {
-                       if (item == null)
-                               throw new ArgumentNullException ("item");
-
                        list.Add (item);
                }
 
index b267bd7c98e4e10fef7e93e91cebdf63dedca924..baff3cc32b181579cbcbb199970fde60290d7cb4 100644 (file)
@@ -44,6 +44,9 @@ namespace MonoTests.System
                        Assert.AreEqual (JsonType.Array, j.JsonType, "type");
                        var str = j.ToString ();
                        Assert.AreEqual (str, "[1, 2, 3, null]");
+                       ((JsonArray) j).Add (null);
+                       str = j.ToString ();
+                       Assert.AreEqual (str, "[1, 2, 3, null, null]");
                }
 
                // Test that we correctly serialize JsonObject with null elements.
index baa6dd9f0d26cc6a219c5187164013043009be9d..c9fd2354abe136be56708c73b9a2bf30ff6f2098 100644 (file)
@@ -96,7 +96,7 @@ namespace System.Net.Http
                                return timeout;
                        }
                        set {
-                               if (value != System.Threading.Timeout.InfiniteTimeSpan && value < TimeSpan.Zero)
+                               if (value != System.Threading.Timeout.InfiniteTimeSpan && (value <= TimeSpan.Zero || value.Ticks > int.MaxValue))
                                        throw new ArgumentOutOfRangeException ();
 
                                timeout = value;
index 8344c26cc68687b585f7be3a8ef3dd08c2f36328..c87bb7562a16337730f027439914e8bfcfb2b383 100644 (file)
@@ -308,6 +308,18 @@ namespace MonoTests.System.Net.Http
                                Assert.Fail ("#2");
                        } catch (ArgumentOutOfRangeException) {
                        }
+
+                       try {
+                               client.Timeout = TimeSpan.Zero;
+                               Assert.Fail ("#3");
+                       } catch (ArgumentOutOfRangeException) {
+                       }
+
+                       try {
+                               client.Timeout = new TimeSpan(int.MaxValue + 1L);
+                               Assert.Fail ("#3");
+                       } catch (ArgumentOutOfRangeException) {
+                       }
                }
 
                [Test]
index 128b8c983b134408a2056bddd9aec8cd09fc2c2e..e94898a5c3863487d63de1900d08563c96fae40c 100644 (file)
@@ -1239,7 +1239,7 @@ namespace System.Runtime.InteropServices
 
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public extern static IntPtr BufferToBSTR (Array ptr, int slen);
+               extern static IntPtr BufferToBSTR (Array ptr, int slen);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern static IntPtr UnsafeAddrOfPinnedArrayElement (Array arr, int index);
diff --git a/mcs/errors/cs0131-6.cs b/mcs/errors/cs0131-6.cs
new file mode 100644 (file)
index 0000000..8af3e93
--- /dev/null
@@ -0,0 +1,15 @@
+// CS0131: The left-hand side of an assignment must be a variable, a property or an indexer
+// Line: 8
+
+class X
+{
+       void Test ()
+       {
+               Foo () = 1;
+       }
+
+       static int Foo ()
+       {
+               return 1;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0199-2.cs b/mcs/errors/cs0199-2.cs
new file mode 100644 (file)
index 0000000..efad7c8
--- /dev/null
@@ -0,0 +1,12 @@
+// CS0199: A static readonly field `X.f' cannot be passed ref or out (except in a static constructor)
+// Line: 10
+
+class X
+{
+       static readonly int f = 0;
+
+       public static void Main ()
+       {
+               ref int j = ref f;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0206-5.cs b/mcs/errors/cs0206-5.cs
new file mode 100644 (file)
index 0000000..bd9691f
--- /dev/null
@@ -0,0 +1,12 @@
+// CS0206: A property, indexer or dynamic member access may not be passed as `ref' or `out' parameter
+// Line: 10
+
+class X
+{
+       static int P { get; set; }
+
+       static void Main ()
+       {
+               ref int rl = ref P;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs1503-17.cs b/mcs/errors/cs1503-17.cs
new file mode 100644 (file)
index 0000000..23921ed
--- /dev/null
@@ -0,0 +1,31 @@
+// CS1503: Argument `#1' cannot convert `ref long' expression to type `ref int'
+// Line: 18
+
+using System;
+
+class X
+{
+       long field;
+
+       static void Main ()
+       {
+               var x = new X ();
+               x.Run ();
+       }
+
+       void Run ()
+       {
+               Test (ref Prop);
+       }
+
+       static int Test (ref int y)
+       {
+               return y;
+       }
+
+       ref long Prop {
+               get {
+                       return ref field;
+               }
+       }
+}
diff --git a/mcs/errors/cs1547-13.cs b/mcs/errors/cs1547-13.cs
new file mode 100644 (file)
index 0000000..1b3f8e1
--- /dev/null
@@ -0,0 +1,7 @@
+// CS1547: Keyword `void' cannot be used in this context
+// Line: 6
+
+interface IA
+{
+       ref void Foo ();
+}
diff --git a/mcs/errors/cs1644-55.cs b/mcs/errors/cs1644-55.cs
new file mode 100644 (file)
index 0000000..58384a6
--- /dev/null
@@ -0,0 +1,11 @@
+// CS1644: Feature `byref locals and returns' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 9
+// Compiler options: -langversion:6
+
+class Text
+{
+       static ref long Foo ()
+       {
+               throw new System.NotImplementedException ();
+       }
+}
diff --git a/mcs/errors/cs1715-3.cs b/mcs/errors/cs1715-3.cs
new file mode 100644 (file)
index 0000000..d3cd5da
--- /dev/null
@@ -0,0 +1,16 @@
+// CS1715: `B.Foo': type must be `int' to match overridden member `A.Foo'
+// Line: 11
+
+public abstract class A
+{
+       public abstract ref int Foo { get; }
+}
+
+public class B : A
+{
+       public override ref long Foo {
+               get {
+                       throw null;
+               }
+       }
+}
\ No newline at end of file
index f8a89b25659474ba368650c02a016c41b8197656..a1dd2e36d1591c8f4bd3fdcb8e8dad9daea66c9a 100644 (file)
@@ -1,4 +1,4 @@
-// CS1764: Cannot use fixed local `p' inside an anonymous method, lambda expression or query expression
+// CS1764: Cannot use fixed variable `p' inside an anonymous method, lambda expression or query expression
 // Line: 10
 // Compiler options: -unsafe
 
diff --git a/mcs/errors/cs8145.cs b/mcs/errors/cs8145.cs
new file mode 100644 (file)
index 0000000..cf3c508
--- /dev/null
@@ -0,0 +1,7 @@
+// CS8145: Auto-implemented properties cannot return by reference
+// Line: 6
+
+public class X
+{
+       ref string TestProp { get; }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8146.cs b/mcs/errors/cs8146.cs
new file mode 100644 (file)
index 0000000..758804c
--- /dev/null
@@ -0,0 +1,7 @@
+// CS8146: `X.TestProp': property and indexer which return by reference must have a get accessor
+// Line: 6
+
+public class X
+{
+       ref string TestProp { set; }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8147-2.cs b/mcs/errors/cs8147-2.cs
new file mode 100644 (file)
index 0000000..a4375d2
--- /dev/null
@@ -0,0 +1,14 @@
+// CS8147: `X.this[int]': property and indexer which return by reference cannot have set accessors
+// Line: 6
+
+public class X
+{
+       ref string this [int arg] { 
+               set {
+
+               }
+               get {
+
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8147.cs b/mcs/errors/cs8147.cs
new file mode 100644 (file)
index 0000000..a006a4d
--- /dev/null
@@ -0,0 +1,14 @@
+// CS8147: `X.TestProp': property and indexer which return by reference cannot have set accessors
+// Line: 6
+
+public class X
+{
+       ref string TestProp { 
+               set {
+
+               }
+               get {
+
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8148-2.cs b/mcs/errors/cs8148-2.cs
new file mode 100644 (file)
index 0000000..1961026
--- /dev/null
@@ -0,0 +1,16 @@
+// CS8148: `B.Foo': must return by reference to match overridden member `A.Foo'
+// Line: 11
+
+public abstract class A
+{
+       public abstract ref int Foo { get; }
+}
+
+public class B : A
+{
+       public override long Foo {
+               get {
+                       throw null;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8148.cs b/mcs/errors/cs8148.cs
new file mode 100644 (file)
index 0000000..1e91789
--- /dev/null
@@ -0,0 +1,15 @@
+// CS8148: `B.Foo()': must not return by reference to match overridden member `A.Foo()'
+// Line: 11
+
+public abstract class A
+{
+       public abstract int Foo ();
+}
+
+public class B : A
+{
+       public override ref int Foo ()
+       {
+
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8149-2.cs b/mcs/errors/cs8149-2.cs
new file mode 100644 (file)
index 0000000..3514769
--- /dev/null
@@ -0,0 +1,14 @@
+// CS8149: By-reference returns can only be used in lambda expressions that return by reference
+// Line: 12
+
+using System;
+
+class A
+{
+       int p;
+       
+       void Test ()
+       {
+               Action a = () => ref p;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8149.cs b/mcs/errors/cs8149.cs
new file mode 100644 (file)
index 0000000..351dd54
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8149: By-reference returns can only be used in methods that return by reference
+// Line: 10
+
+class A
+{
+       int p;
+
+       int Test ()
+       {
+               return ref p;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8150.cs b/mcs/errors/cs8150.cs
new file mode 100644 (file)
index 0000000..fd4ef7a
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8150: By-reference return is required when method returns by reference
+// Line: 10
+
+class A
+{
+       int p;
+
+       ref int Test ()
+       {
+               return p;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8151.cs b/mcs/errors/cs8151.cs
new file mode 100644 (file)
index 0000000..934faef
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8151: The return by reference expression must be of type `string' because this method returns by reference
+// Line: 10
+
+public class X
+{
+       int field;
+
+       ref string TestMethod ()
+       {
+               return ref field;
+       }
+}
diff --git a/mcs/errors/cs8152.cs b/mcs/errors/cs8152.cs
new file mode 100644 (file)
index 0000000..45546ad
--- /dev/null
@@ -0,0 +1,14 @@
+// CS8152: `C' does not implement interface member `IA.Foo()' and the best implementing candidate `C.Foo()' return type `void' does not return by reference
+// Line: 11
+
+interface IA
+{
+       ref char Foo ();
+}
+
+public class C : IA
+{
+       public void Foo ()
+       {
+       }
+}
diff --git a/mcs/errors/cs8153.cs b/mcs/errors/cs8153.cs
new file mode 100644 (file)
index 0000000..d36f110
--- /dev/null
@@ -0,0 +1,24 @@
+// CS8153: An expression tree lambda cannot contain a call to a method, property, or indexer that returns by reference
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class X
+{
+       void Foo ()
+       {
+               Expression<Func<int>> e = () => Test (ref this[0]);
+       }
+
+       static int Test (ref int y)
+       {
+               return y;
+       }
+
+       ref int this [int y] {
+               get {
+                       throw null;
+               }
+       }
+}
diff --git a/mcs/errors/cs8154.cs b/mcs/errors/cs8154.cs
new file mode 100644 (file)
index 0000000..ed98513
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8154: The body of `TestClass.TestFunction()' cannot be an iterator block because the method returns by reference
+// Line: 10
+
+class TestClass
+{
+    int x;
+
+    ref int TestFunction()
+    {
+        yield return x;
+    }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8155.cs b/mcs/errors/cs8155.cs
new file mode 100644 (file)
index 0000000..45d8b4e
--- /dev/null
@@ -0,0 +1,16 @@
+// CS8155: Lambda expressions that return by reference cannot be converted to expression trees
+// Line: 14
+
+using System.Linq.Expressions;
+
+class TestClass
+{
+    static int x;
+
+    delegate ref int D ();
+
+    static void Main ()
+    {
+        Expression<D> e = () => ref x;
+    }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8156-2.cs b/mcs/errors/cs8156-2.cs
new file mode 100644 (file)
index 0000000..7507ec4
--- /dev/null
@@ -0,0 +1,16 @@
+// CS8156: An expression cannot be used in this context because it may not be returned by reference
+// Line: 8
+
+class X
+{
+       int Prop {
+               get {
+                       return 1;
+               }
+       }
+
+       ref int Test ()
+       {
+               return ref Prop;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8156.cs b/mcs/errors/cs8156.cs
new file mode 100644 (file)
index 0000000..fe3f6b7
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8156: An expression cannot be used in this context because it may not be returned by reference
+// Line: 8
+
+class Test
+{
+       ref int Foo ()
+       {
+               return ref 2;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8157.cs b/mcs/errors/cs8157.cs
new file mode 100644 (file)
index 0000000..35d700f
--- /dev/null
@@ -0,0 +1,13 @@
+// CS8157: Cannot return `r' by reference because it was initialized to a value that cannot be returned by reference
+// Line: 11
+
+struct S
+{
+       int i;
+
+       ref int M ()
+       {
+               ref int r = ref i;
+               return ref r;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8160.cs b/mcs/errors/cs8160.cs
new file mode 100644 (file)
index 0000000..2b4ea42
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8160: A readonly field cannot be returned by reference
+// Line: 10
+
+class X
+{
+       readonly int f = 0;
+
+       ref int Test ()
+       {
+               return ref f;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8161.cs b/mcs/errors/cs8161.cs
new file mode 100644 (file)
index 0000000..0d028a1
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8161: A static readonly field cannot be returned by reference
+// Line: 10
+
+class X
+{
+       static readonly int f;
+
+       static ref int Test ()
+       {
+               return ref f;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8170-2.cs b/mcs/errors/cs8170-2.cs
new file mode 100644 (file)
index 0000000..dbd76a4
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8170:
+// Line: 10
+
+public struct S
+{
+       int f;
+
+       public ref S Foo ()
+       {
+               return ref f;
+       }
+}
diff --git a/mcs/errors/cs8170.cs b/mcs/errors/cs8170.cs
new file mode 100644 (file)
index 0000000..142e1a1
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8170:
+// Line: 8
+
+public struct S
+{
+       public ref S Foo ()
+       {
+               return ref this;
+       }
+}
diff --git a/mcs/errors/cs8171.cs b/mcs/errors/cs8171.cs
new file mode 100644 (file)
index 0000000..36eae2c
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8171: Cannot initialize a by-value variable `l' with a reference expression
+// Line: 10
+
+class Test
+{
+       int field;
+
+       void Foo ()
+       {
+               int l = ref field;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8172.cs b/mcs/errors/cs8172.cs
new file mode 100644 (file)
index 0000000..7ddd383
--- /dev/null
@@ -0,0 +1,12 @@
+// CS8172: Cannot initialize a by-reference variable `j' with a value
+// Line: 10
+
+class X
+{
+       static int f;
+
+       public static void Main ()
+       {
+               ref int j = f;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8173.cs b/mcs/errors/cs8173.cs
new file mode 100644 (file)
index 0000000..7c7d894
--- /dev/null
@@ -0,0 +1,13 @@
+// CS8173: The expression must be of type `long' because it is being assigned by reference
+// Line: 11
+
+public class X
+{
+       int field;
+
+       public static void Main ()
+       {
+               int i = 5;
+               ref long j = ref i;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8174.cs b/mcs/errors/cs8174.cs
new file mode 100644 (file)
index 0000000..888711a
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8174: A declaration of a by-reference variable must have an initializer
+// Line: 8
+
+class X
+{
+       public static void Main ()
+       {
+               ref int j;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8175.cs b/mcs/errors/cs8175.cs
new file mode 100644 (file)
index 0000000..4ef39db
--- /dev/null
@@ -0,0 +1,17 @@
+// CS8175: Cannot use by-reference variable `v' inside an anonymous method, lambda expression, or query expression
+// Line: 14
+
+using System;
+
+public class Test
+{
+       public static void Main()
+       {
+               var arr = new int [1];
+               ref var v = ref arr [0];
+
+               Action a = delegate {
+                       ref var v2 = ref v;
+               };
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8176.cs b/mcs/errors/cs8176.cs
new file mode 100644 (file)
index 0000000..514c0b2
--- /dev/null
@@ -0,0 +1,15 @@
+// CS8176: Iterators cannot use by-reference variables
+// Line: 12
+
+using System.Collections.Generic;
+
+class X
+{
+       int x;
+
+       IEnumerable<int> Test ()
+       {
+               ref int y = ref x;
+               yield break;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8177.cs b/mcs/errors/cs8177.cs
new file mode 100644 (file)
index 0000000..414ece1
--- /dev/null
@@ -0,0 +1,15 @@
+// CS8177: Async methods cannot use by-reference variables
+// Line: 12
+
+using System.Threading.Tasks;
+
+class X
+{
+       int x;
+
+       async Task Test ()
+       {
+               ref int y = ref x;
+               await Task.Yield ();
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8178-2.cs b/mcs/errors/cs8178-2.cs
new file mode 100644 (file)
index 0000000..e61b7d9
--- /dev/null
@@ -0,0 +1,20 @@
+// CS8178: `await' cannot be used in an expression containing a call to `X.this[int]' because it returns by reference
+// Line: 12
+
+using System.Threading.Tasks;
+
+class X
+{
+       int x;
+
+       async Task Test ()
+       {
+               Foo (ref this [await Task.FromResult (1)]);
+       }
+
+       ref int this [int arg] => ref x;
+
+       static void Foo (ref int arg)
+       {
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8178.cs b/mcs/errors/cs8178.cs
new file mode 100644 (file)
index 0000000..6f77962
--- /dev/null
@@ -0,0 +1,24 @@
+// CS8178: `await' cannot be used in an expression containing a call to `X.Wrap(int)' because it returns by reference
+// Line: 12
+
+using System.Threading.Tasks;
+
+class X
+{
+       int x;
+
+       async Task Test ()
+       {
+               Foo (ref Wrap (await Task.FromResult (1))) = 4;
+       }
+
+       ref int Wrap (int arg)
+       {
+               return ref x;
+       }
+
+       static ref int Foo (ref int arg)
+       {
+               return ref arg;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8189.cs b/mcs/errors/cs8189.cs
new file mode 100644 (file)
index 0000000..909ec3b
--- /dev/null
@@ -0,0 +1,17 @@
+// CS8189: By reference return delegate does not match `C.D()' return type
+// Line: 15
+
+class C
+{
+       delegate ref int D ();
+
+       static int M ()
+       {
+               return 1;
+       }
+
+       static void Main ()
+       {
+               D d = new D (M);
+       }
+}
\ No newline at end of file
index 40f81ded9703c88ae78fa849f4db1d028545e0bf..c9ed9317350d471d891e70fc18423b7a99c1bd44 100644 (file)
@@ -22,3 +22,8 @@ cs8129.cs NO ERROR
 cs8141.cs
 cs8141-2.cs
 cs8144.cs
+cs8157.cs NO ERROR
+cs8160.cs
+cs8161.cs
+cs8170.cs NO ERROR
+cs8170-2.cs
index 00fd56d8a64a23743451fc6b829f07abe77f3cec..8421b4dfbfcc766e11af46e124c59be508d68165 100644 (file)
@@ -104,12 +104,17 @@ namespace Mono.CSharp
                        return Clone (Expr.Clone (clonectx));
                }
 
-               public virtual Expression CreateExpressionTree (ResolveContext ec)
+               public virtual Expression CreateExpressionTree (ResolveContext rc)
                {
+                       if (Type.Kind == MemberKind.ByRef) {
+                               rc.Report.Error (8153, Expr.Location, "An expression tree lambda cannot contain a call to a method, property, or indexer that returns by reference");
+                               return null;
+                       }
+
                        if (ArgType == AType.Default)
-                               ec.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter");
+                               rc.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter");
 
-                       return Expr.CreateExpressionTree (ec);
+                       return Expr.CreateExpressionTree (rc);
                }
 
 
@@ -126,12 +131,16 @@ namespace Mono.CSharp
                                return;
                        }
 
+                       if (Expr.Type.Kind == MemberKind.ByRef) {
+                               Expr.Emit (ec);
+                               return;
+                       }
+
                        AddressOp mode = AddressOp.Store;
                        if (ArgType == AType.Ref)
                                mode |= AddressOp.Load;
 
-                       IMemoryLocation ml = (IMemoryLocation) Expr;
-                       ml.AddressOf (ec, mode);
+                       ((IMemoryLocation)Expr).AddressOf (ec, mode);
                }
 
                public Argument EmitToField (EmitContext ec, bool cloneResult)
@@ -421,17 +430,19 @@ namespace Mono.CSharp
                        return all;
                }
 
-               public static Arguments CreateForExpressionTree (ResolveContext ec, Arguments args, params Expression[] e)
+               public static Arguments CreateForExpressionTree (ResolveContext rc, Arguments args, params Expression[] e)
                {
                        Arguments all = new Arguments ((args == null ? 0 : args.Count) + e.Length);
                        for (int i = 0; i < e.Length; ++i) {
-                               if (e [i] != null)
-                                       all.Add (new Argument (e[i]));
+                               var expr = e [i];
+                               if (expr != null) {
+                                       all.Add (new Argument (expr));
+                               }
                        }
 
                        if (args != null) {
                                foreach (Argument a in args.args) {
-                                       Expression tree_arg = a.CreateExpressionTree (ec);
+                                       Expression tree_arg = a.CreateExpressionTree (rc);
                                        if (tree_arg != null)
                                                all.Add (new Argument (tree_arg));
                                }
index 48b1c6921f3c897fe0b8e5780e59fe5f34a514aa..07bf45f12ef73f8e0a8527053f96bb599948793e 100644 (file)
@@ -3527,7 +3527,10 @@ namespace Mono.CSharp
                        var base_member_type = ((IInterfaceMemberSpec)base_member).MemberType;
                        if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
                                Report.SymbolRelatedToPreviousError (base_member);
-                               if (this is PropertyBasedMember) {
+                               if (((base_member_type.Kind ^ MemberType.Kind) & MemberKind.ByRef) != 0) {
+                                       Report.Error (8148, Location, "`{0}': must {2}return by reference to match overridden member `{1}'",
+                                                     GetSignatureForError (), base_member.GetSignatureForError (), base_member_type.Kind == MemberKind.ByRef ? "" : "not ");
+                               } else if (this is PropertyBasedMember) {
                                        Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
                                                GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
                                } else {
index 8fe0e2026ca5842fdc286d456bf41a536f79456b..b11477c104394b7bc77075d6e4fa02827797529e 100644 (file)
@@ -1503,6 +1503,11 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
+                       if (expr is ReferenceExpression) {
+                               // Only identify conversion is allowed
+                               return null;
+                       }
+
                        e = ImplicitNumericConversion (expr, expr_type, target_type);
                        if (e != null)
                                return e;
index 5f885a77763b8ccebc07be47fb643c310be926f5..648effd7f1095c7731e5ed6797a6bd3ceb20dd3e 100644 (file)
@@ -1161,7 +1161,7 @@ constant_initializer_expr
 field_declaration
        : opt_attributes
          opt_modifiers
-         member_type IDENTIFIER
+         ref_member_type IDENTIFIER
          {
                lexer.parsing_generic_declaration = false;
 
@@ -1364,10 +1364,29 @@ method_declaration
          }
        ;
 
+ref_member_type
+       : member_type
+         {
+               $$ = $1;
+         }
+       | REF
+         {
+               lexer.parsing_generic_declaration = true;
+         }
+         type
+         {
+               if (lang_version < LanguageVersion.V_7) {
+                       FeatureIsNotAvailable (GetLocation ($1), "byref locals and returns");
+               }
+
+               $$ = new ReferenceTypeExpr ((FullNamedExpression) $3, GetLocation ($1));
+         }
+       ;
+
 method_header
        : opt_attributes
          opt_modifiers
-         member_type
+         ref_member_type
          method_declaration_name OPEN_PARENS
          {
                valid_param_mod = ParameterModifierType.All;
@@ -1452,7 +1471,7 @@ method_header
          }
        | opt_attributes
          opt_modifiers
-         member_type
+         ref_member_type
          modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
          {
                MemberName name = (MemberName) $5;
@@ -1473,7 +1492,7 @@ method_header
          }
        | opt_attributes
          opt_modifiers
-         member_type
+         ref_member_type
          method_declaration_name error
          {
                Error_SyntaxError (yyToken);
@@ -1534,7 +1553,7 @@ expression_block
                ++lexer.parsing_block;
                start_block (GetLocation ($1));
         }
-        expression SEMICOLON
+        lambda_arrow_expression SEMICOLON
         {
                lexer.parsing_block = 0;
                current_block.AddStatement (new ContextualReturn ((Expression) $3));
@@ -1838,7 +1857,7 @@ arglist_modifier
 property_declaration
        : opt_attributes
          opt_modifiers
-         member_type
+         ref_member_type
          member_declaration_name
          {
                lexer.parsing_generic_declaration = false;
@@ -1865,6 +1884,16 @@ property_declaration
 
                if (doc_support)
                        current_property.DocComment = ConsumeStoredComment ();
+
+               if ($3 is ReferenceTypeExpr) {
+                       if (current_property.Get == null) {
+                               report.Error (8146, GetLocation ($4), "`{0}': property and indexer which return by reference must have a get accessor", current_property.GetSignatureForError ());
+                       }
+
+                       if (current_property.Set != null) {
+                               report.Error (8147, GetLocation ($4), "`{0}': property and indexer which return by reference cannot have set accessors", current_property.GetSignatureForError ());
+                       }
+               }
          }
          CLOSE_BRACE
          {
@@ -1877,7 +1906,7 @@ property_declaration
          }
        | opt_attributes
          opt_modifiers
-         member_type
+         ref_member_type
          member_declaration_name
          {
                lexer.parsing_generic_declaration = false;
@@ -1939,7 +1968,7 @@ property_initializer
 
 indexer_declaration
        : opt_attributes opt_modifiers
-         member_type indexer_declaration_name OPEN_BRACKET
+         ref_member_type indexer_declaration_name OPEN_BRACKET
          {
                valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue;
          }
@@ -1979,6 +2008,16 @@ indexer_declaration
          
                if (doc_support)
                        current_property.DocComment = ConsumeStoredComment ();
+
+               if ($3 is ReferenceTypeExpr) {
+                       if (current_property.Get == null) {
+                               report.Error (8146, GetLocation ($4), "`{0}': property and indexer which return by reference must have a get accessor", current_property.GetSignatureForError ());
+                       }
+
+                       if (current_property.Set != null) {
+                               report.Error (8147, GetLocation ($4), "`{0}': property and indexer which return by reference cannot have set accessors", current_property.GetSignatureForError ());
+                       }
+               }
                        
                current_property = null;                
          }
@@ -2938,7 +2977,7 @@ delegate_declaration
        : opt_attributes
          opt_modifiers
          DELEGATE
-         member_type type_declaration_name
+         ref_member_type type_declaration_name
          OPEN_PARENS
          {
                valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue;
@@ -5109,7 +5148,7 @@ lambda_expression_body
        : {
                start_block (Location.Null);
          }
-         expression    // All expressions must handle error or current block won't be restored and breaking ast completely
+         lambda_arrow_expression       // All expressions must handle error or current block won't be restored and breaking ast completely
          {
                Block b = end_block (Location.Null);
                b.IsCompilerGenerated = true;
@@ -5129,6 +5168,11 @@ lambda_expression_body
          }
        ;
 
+lambda_arrow_expression
+       : expression
+       | reference_expression
+       ;
+
 expression_or_error
        : expression
        | error
@@ -5939,6 +5983,28 @@ block_variable_declaration
                current_variable = null;
                lbag.AddLocation ($$, GetLocation ($1), GetLocation ($7));
          }
+       | REF variable_type identifier_inside_body
+         {
+               if (lang_version < LanguageVersion.V_7) {
+                       FeatureIsNotAvailable (GetLocation ($1), "byref locals and returns");
+               }
+
+               var lt = (LocatedToken) $3;
+               var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ByRef, lt.Location);
+               current_block.AddLocalName (li);
+               current_variable = new BlockVariable ((FullNamedExpression) $2, li);
+         }
+         opt_local_variable_initializer opt_variable_declarators SEMICOLON
+         {
+               $$ = current_variable;
+               current_variable = null;
+               if ($5 != null) {
+                       lbag.AddLocation ($$, PopLocation (), GetLocation ($7));
+               } else {
+                       report.Error (8174, GetLocation ($3), "A declaration of a by-reference variable must have an initializer");
+                       lbag.AddLocation ($$, GetLocation ($7));
+               }
+         }
        ;
 
 opt_local_variable_initializer
@@ -6047,6 +6113,18 @@ block_variable_initializer
                report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type");
                $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1));          
          }
+       | reference_expression
+       ;
+
+reference_expression
+       : REF expression
+         {
+               if (lang_version < LanguageVersion.V_7) {
+                       FeatureIsNotAvailable (GetLocation ($1), "byref locals and returns");
+               }
+
+               $$ = new ReferenceExpression ((Expression) $2, GetLocation ($1));
+         }
        ;
 
 expression_statement
@@ -6522,6 +6600,11 @@ return_statement
                $$ = new Return ((Expression) $2, GetLocation ($1));
                lbag.AddStatement ($$, GetLocation ($3));
          }
+       | RETURN reference_expression SEMICOLON
+         {
+               $$ = new Return ((Expression) $2, GetLocation ($1));
+               lbag.AddStatement ($$, GetLocation ($3));
+         }
        | RETURN expression error
          {
                Error_SyntaxError (yyToken);
index 368bb19c1b165d507f90e877ec40a5b993217093..80eb7e265f1395bec67ce6ba117212b0474a80b5 100644 (file)
@@ -587,8 +587,7 @@ namespace Mono.CSharp {
                                rt = ec.BuiltinTypes.Object;
 
                        if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) {
-                               Expression ret_expr = new TypeExpression (delegate_method.ReturnType, loc);
-                               Error_ConversionFailed (ec, delegate_method, ret_expr);
+                               Error_ConversionFailed (ec, delegate_method, delegate_method.ReturnType);
                        }
 
                        if (method_group.IsConditionallyExcluded) {
@@ -639,7 +638,7 @@ namespace Mono.CSharp {
                        method_group.FlowAnalysis (fc);
                }
 
-               void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type)
+               void Error_ConversionFailed (ResolveContext ec, MethodSpec method, TypeSpec return_type)
                {
                        var invoke_method = Delegate.GetInvokeMethod (type);
                        string member_name = method_group.InstanceExpression != null ?
@@ -661,6 +660,12 @@ namespace Mono.CSharp {
                                return;
                        }
 
+                       if (invoke_method.ReturnType.Kind == MemberKind.ByRef) {
+                               ec.Report.Error (8189, loc, "By reference return delegate does not match `{0}' return type",
+                                       Delegate.FullDelegateDesc (invoke_method));
+                               return;
+                       }
+
                        ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
                                return_type.GetSignatureForError (), member_name,
                                invoke_method.ReturnType.GetSignatureForError (), Delegate.FullDelegateDesc (invoke_method));
index 9486475305452e2ab5c326d264e3f0954e58a661..490bcfb518e5c4a78535f71c07bc2e6c8dde9ce4 100644 (file)
@@ -303,7 +303,12 @@ namespace Mono.CSharp {
                                return;
 
                        string from_type = type.GetSignatureForError ();
+                       if (type.Kind == MemberKind.ByRef)
+                               from_type = "ref " + from_type;
                        string to_type = target.GetSignatureForError ();
+                       if (target.Kind == MemberKind.ByRef)
+                               to_type = "ref " + to_type;
+
                        if (from_type == to_type) {
                                from_type = type.GetSignatureForErrorIncludingAssemblyName ();
                                to_type = target.GetSignatureForErrorIncludingAssemblyName ();
@@ -559,18 +564,18 @@ namespace Mono.CSharp {
                public Expression ResolveLValue (ResolveContext ec, Expression right_side)
                {
                        int errors = ec.Report.Errors;
-                       bool out_access = right_side == EmptyExpression.OutAccess;
+                       //bool out_access = right_side == EmptyExpression.OutAccess;
 
                        Expression e = DoResolveLValue (ec, right_side);
 
-                       if (e != null && out_access && !(e is IMemoryLocation)) {
+                       //if (e != null && out_access && !(e is IMemoryLocation)) {
                                // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
                                //        Enabling this 'throw' will "only" result in deleting useless code elsewhere,
 
                                //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
                                //                                e.GetType () + " " + e.GetSignatureForError ());
-                               e = null;
-                       }
+                       //      e = null;
+                       //}
 
                        if (e == null) {
                                if (errors == ec.Report.Errors) {
@@ -5417,6 +5422,11 @@ namespace Mono.CSharp {
                                        if (arg_type == InternalType.VarOutType)
                                                return 0;
 
+                                       var ref_arg_type = arg_type as ReferenceContainer;
+                                       if (ref_arg_type != null) {
+                                               arg_type = ref_arg_type.Element;
+                                       }
+
                                        //
                                        // Do full equality check after quick path
                                        //
@@ -5982,13 +5992,13 @@ namespace Mono.CSharp {
                        int arg_count = args == null ? 0 : args.Count;
 
                        for (; a_idx < arg_count; a_idx++, ++a_pos) {
-                               a = args[a_idx];
+                               a = args [a_idx];
                                if (a == null)
                                        continue;
 
                                if (p_mod != Parameter.Modifier.PARAMS) {
                                        p_mod = cpd.FixedParameters [a_idx].ModFlags;
-                                       pt = ptypes[a_idx];
+                                       pt = ptypes [a_idx];
                                        has_unsafe_arg |= pt.IsPointer;
 
                                        if (p_mod == Parameter.Modifier.PARAMS) {
@@ -6018,6 +6028,14 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
+                                       var ref_arg_type = arg_type as ReferenceContainer;
+                                       if (ref_arg_type != null) {
+                                               if (ref_arg_type.Element != pt)
+                                                       break;
+
+                                               return true;
+                                       }
+
                                        if (!TypeSpecComparer.IsEqual (arg_type, pt))
                                                break;
                                }
@@ -6525,12 +6543,12 @@ namespace Mono.CSharp {
                                                GetSignatureForError ());
                                }
 
-                               return null;
+                               return ErrorExpression.Instance;
                        }
 
                        if (right_side == EmptyExpression.LValueMemberAccess) {
                                // Already reported as CS1648/CS1650
-                               return null;
+                               return ErrorExpression.Instance;
                        }
 
                        if (right_side == EmptyExpression.LValueMemberOutAccess) {
@@ -6541,7 +6559,7 @@ namespace Mono.CSharp {
                                        rc.Report.Error (1649, loc, "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
                                                GetSignatureForError ());
                                }
-                               return null;
+                               return ErrorExpression.Instance;
                        }
 
                        if (IsStatic) {
@@ -6552,7 +6570,7 @@ namespace Mono.CSharp {
                                        GetSignatureForError ());
                        }
 
-                       return null;
+                       return ErrorExpression.Instance;
                }
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
@@ -7341,6 +7359,15 @@ namespace Mono.CSharp {
                                Error_NullPropagatingLValue (rc);
 
                        if (right_side == EmptyExpression.OutAccess) {
+                               if (best_candidate?.MemberType.Kind == MemberKind.ByRef) {
+                                       if (Arguments?.ContainsEmitWithAwait () == true) {
+                                               rc.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference",
+                                                       GetSignatureForError ());
+                                       }
+
+                                       return this;
+                               }
+
                                // TODO: best_candidate can be null at this point
                                INamedBlockVariable variable = null;
                                if (best_candidate != null && rc.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, rc.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
index 113ed29910c155493a769098bc9e058a05712a96..3407b9faf884118562ea008f55c838c4b5d885bd 100644 (file)
@@ -6562,18 +6562,19 @@ namespace Mono.CSharp
                                return;
                        }
 
+                       bool dereference = IsRef && !(source is ReferenceExpression);
                        New n_source = source as New;
                        if (n_source != null && n_source.CanEmitOptimizedLocalTarget (ec)) {
                                if (!n_source.Emit (ec, this)) {
                                        if (leave_copy) {
                                                EmitLoad (ec);
-                                               if (IsRef)
+                                               if (dereference)
                                                        ec.EmitLoadFromPtr (type);
                                        }
                                        return;
                                }
                        } else {
-                               if (IsRef)
+                               if (dereference)
                                        EmitLoad (ec);
 
                                source.Emit (ec);
@@ -6581,13 +6582,13 @@ namespace Mono.CSharp
 
                        if (leave_copy) {
                                ec.Emit (OpCodes.Dup);
-                               if (IsRef) {
+                               if (dereference) {
                                        temp = new LocalTemporary (Type);
                                        temp.Store (ec);
                                }
                        }
 
-                       if (IsRef)
+                       if (dereference)
                                ec.EmitStoreFromPtr (type);
                        else
                                Variable.EmitAssign (ec);
@@ -6671,7 +6672,7 @@ namespace Mono.CSharp
                }
 
                public override bool IsRef {
-                       get { return false; }
+                       get { return local_info.IsByRef; }
                }
 
                public override string Name {
@@ -6712,7 +6713,11 @@ namespace Mono.CSharp
                                        AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc);
                                } else if (local_info.IsFixed) {
                                        ec.Report.Error (1764, loc,
-                                               "Cannot use fixed local `{0}' inside an anonymous method, lambda expression or query expression",
+                                               "Cannot use fixed variable `{0}' inside an anonymous method, lambda expression or query expression",
+                                               GetSignatureForError ());
+                               } else if (local_info.IsByRef) {
+                                       ec.Report.Error (8175, loc,
+                                               "Cannot use by-reference variable `{0}' inside an anonymous method, lambda expression, or query expression",
                                                GetSignatureForError ());
                                }
 
@@ -7134,7 +7139,7 @@ namespace Mono.CSharp
                protected override Expression DoResolve (ResolveContext rc)
                {
                        ResolveConditionalAccessReceiver (rc);
-                       return DoResolveInvocation (rc);
+                       return DoResolveInvocation (rc, null);
                }
 
                public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
@@ -7161,10 +7166,21 @@ namespace Mono.CSharp
                                return res.Resolve (rc);
                        }
 
+                       if (right_side != null) {
+                               if (eclass != ExprClass.Unresolved)
+                                       return this;
+
+                               var res = DoResolveInvocation (rc, right_side);
+                               if (res == null)
+                                       return null;
+
+                               return res;
+                       }
+
                        return base.DoResolveLValue (rc, right_side);
                }
 
-               Expression DoResolveInvocation (ResolveContext ec)
+               Expression DoResolveInvocation (ResolveContext ec, Expression rhs)
                {
                        Expression member_expr;
                        var atn = expr as ATypeNameExpression;
@@ -7260,6 +7276,17 @@ namespace Mono.CSharp
                        IsSpecialMethodInvocation (ec, method, loc);
                        
                        eclass = ExprClass.Value;
+
+                       if (type.Kind == MemberKind.ByRef) {
+                               if (rhs == null && arguments?.ContainsEmitWithAwait () == true) {
+                                       ec.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference",
+                                               GetSignatureForError ());
+                               }
+
+                               if (rhs != EmptyExpression.OutAccess)
+                                       return ByRefDereference.Create (this).Resolve (ec);
+                       }
+
                        return this;
                }
 
@@ -11591,6 +11618,39 @@ namespace Mono.CSharp
                }
        }
 
+       class ReferenceTypeExpr : TypeExpr
+       {
+               FullNamedExpression element;
+
+               public ReferenceTypeExpr (FullNamedExpression element, Location loc)
+               {
+                       this.element = element;
+                       this.loc = loc;
+               }
+
+               public override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
+               {
+                       type = element.ResolveAsType (mc);
+                       if (type == null)
+                               return null;
+
+                       eclass = ExprClass.Type;
+                       type = ReferenceContainer.MakeType (mc.Module, type);
+
+                       return type;
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return "ref " + element.GetSignatureForError ();
+               }
+
+               public override object Accept (StructuralVisitor visitor)
+               {
+                       return visitor.Visit (this);
+               }
+       }
+
        class FixedBufferPtr : Expression
        {
                readonly Expression array;
@@ -12918,4 +12978,146 @@ namespace Mono.CSharp
                        return Reachability.CreateUnreachable ();
                }
        }
+
+       class ReferenceExpression : CompositeExpression
+       {
+               public ReferenceExpression (Expression expr, Location loc)
+                       : base (expr)
+               {
+                       this.loc = loc;
+               }
+
+               static bool CanBeByRef (Expression expr)
+               {
+                       if (expr is IAssignMethod)
+                               return true;
+
+                       var invocation = expr as Invocation;
+                       if (invocation?.Type.Kind == MemberKind.ByRef)
+                               return true;
+
+                       return false;
+               }
+
+               public override Expression CreateExpressionTree (ResolveContext rc)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       var res = expr.DoResolveLValue (rc, EmptyExpression.OutAccess);
+                       if (res == null || !CanBeByRef (res)) {
+                               if (res?.Type != InternalType.ErrorType)
+                                       rc.Report.Error (8156, expr.Location, "An expression cannot be used in this context because it may not be returned by reference");
+                               return ErrorExpression.Instance;
+                       }
+
+                       type = res.Type;
+                       var type_container = type as ReferenceContainer;
+                       if (type_container != null)
+                               type = type_container.Element;
+
+                       expr = res;
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       var ml = expr as IMemoryLocation;
+                       if (ml != null)
+                               ml.AddressOf (ec, AddressOp.LoadStore);
+                       else
+                               expr.Emit (ec);
+               }
+
+               public override void Error_ValueCannotBeConverted (ResolveContext rc, TypeSpec target, bool expl)
+               {
+                       rc.Report.Error (8173, loc, "The expression must be of type `{0}' because it is being assigned by reference", target.GetSignatureForError ());
+               }
+       }
+
+       class ByRefDereference : CompositeExpression, IMemoryLocation, IAssignMethod
+       {
+               bool prepared;
+               LocalTemporary temporary;
+
+               private ByRefDereference (Expression expr)
+                       : base (expr)
+               {
+               }
+
+               public static Expression Create (Expression expr)
+               {
+                       var rc = expr.Type as ReferenceContainer;
+                       if (rc == null)
+                               return expr;
+
+                       return new ByRefDereference (expr) {
+                               type = rc.Element
+                       };
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       expr.Emit (ec);
+               }
+
+               public void Emit (EmitContext ec, bool leave_copy)
+               {
+                       Emit (ec);
+                       if (leave_copy) {
+                               ec.Emit (OpCodes.Dup);
+                               temporary = new LocalTemporary (type);
+                               temporary.Store (ec);
+                       }
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
+               {
+                       prepared = isCompound;
+
+                       expr.Emit (ec);
+
+                       if (isCompound)
+                               ec.Emit (OpCodes.Dup);
+                       
+                       source.Emit (ec);
+                       if (leave_copy) {
+                               throw new NotImplementedException ("leave_copy");
+                       }
+                       
+                       ec.EmitStoreFromPtr (type);
+                       
+                       if (temporary != null) {
+                               temporary.Emit (ec);
+                               temporary.Release (ec);
+                       }
+               }
+
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       eclass = ExprClass.Variable;
+                       return this;
+               }
+
+               public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+               {
+                       return DoResolve (rc);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       if (!prepared)
+                               base.Emit(ec);
+                       
+                       ec.EmitLoadFromPtr (type);
+               }
+
+               public override object Accept (StructuralVisitor visitor)
+               {
+                       return visitor.Visit (this);
+               }
+       }
 }
index 1efba64ba575caf08f33deae99bafc47c5fc4e3f..625cd0c773f0588fefcd0b3055c1ddbc20d0e44a 100644 (file)
@@ -1543,6 +1543,9 @@ namespace Mono.CSharp {
                                        if (ec is PointerContainer)
                                                return PointerContainer.MakeType (context.Module, et);
 
+                                       if (ec is ReferenceContainer)
+                                               return ReferenceContainer.MakeType (context.Module, et);
+                                       
                                        throw new NotImplementedException ();
                                }
 
index c0ccf129e74a77fd44b33e4c702b9e69412cd1e6..feb10844b8c7f0eac017a4454d3d7bf8a5d426b2 100644 (file)
@@ -1187,11 +1187,15 @@ namespace Mono.CSharp
                                return;
 
                        if (!CheckType (ret, parent, out iterator_type, out is_enumerable)) {
-                               parent.Compiler.Report.Error (1624, method.Location,
-                                             "The body of `{0}' cannot be an iterator block " +
-                                             "because `{1}' is not an iterator interface type",
-                                             method.GetSignatureForError (),
-                                             ret.GetSignatureForError ());
+                               if (ret.Kind == MemberKind.ByRef) {
+                                       parent.Compiler.Report.Error (8154, method.Location,
+                                                         "The body of `{0}' cannot be an iterator block because the method returns by reference",
+                                                         method.GetSignatureForError ());
+                               } else {
+                                       parent.Compiler.Report.Error (1624, method.Location,
+                                                         "The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",
+                                                         method.GetSignatureForError (), ret.GetSignatureForError ());
+                               }
                                return;
                        }
 
index 9c804ceca575e6730e194e54a8bce5735a24cb81..360c5c9463002d0d8e1956573bfcb688702589e4 100644 (file)
@@ -188,6 +188,11 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
+                       if (Expr is ReferenceExpression) {
+                               ec.Report.Error (8155, Expr.Location, "Lambda expressions that return by reference cannot be converted to expression trees");
+                               return null;
+                       }
+
                        return Expr.CreateExpressionTree (ec);
                }
 
@@ -216,6 +221,12 @@ namespace Mono.CSharp {
                                if (Expr == null)
                                        return false;
 
+                               if (Expr is ReferenceExpression) {
+                                       // CSC: should be different error code
+                                       ec.Report.Error (8149, loc, "By-reference returns can only be used in lambda expressions that return by reference");
+                                       return false;
+                               }
+
                                statement = Expr as ExpressionStatement;
                                if (statement == null) {
                                        var reduced = Expr as IReducedExpressionStatement;
index d132c872bafced81c59fd1eaf5bc8fd8245eb9a1..eebf71b844b8e2a51337bf35a1560c7b13d7134f 100644 (file)
@@ -35,6 +35,7 @@ namespace Mono.CSharp {
                Enum            = 1 << 14,
                Interface       = 1 << 15,
                TypeParameter = 1 << 16,
+               ByRef           = 1 << 17,
 
                ArrayType = 1 << 19,
                PointerType = 1 << 20,
index 1de765fb4ac041eb7926c501e0aeb235c98579ad..d95f8f13956d867d0d60df079a4a10e9ebe98c80 100644 (file)
@@ -748,6 +748,11 @@ namespace Mono.CSharp {
                                                                Report.Error (737, container.Location,
                                                                        "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' is not public",
                                                                        container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ());
+                                                       } else if (mi.ReturnType.Kind == MemberKind.ByRef) {
+                                                               Report.Error (8152, container.Location,
+                                                                       "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not return by reference",
+                                                                       container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError (),
+                                                                       candidate.ReturnType.GetSignatureForError ());
                                                        } else {
                                                                Report.Error (738, container.Location,
                                                                        "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not match interface member return type `{4}'",
index 1dd8a86468eb1ab0f2727a649f67d3273ed6d8cd..3478711470a0fa6d93b668621c5d60392e2fda08 100644 (file)
@@ -879,6 +879,11 @@ namespace Mono.CSharp
                                        return false;
                                }
 
+                               if (MemberType.Kind == MemberKind.ByRef) {
+                                       Report.Error (8145, Location, "Auto-implemented properties cannot return by reference");
+                                       return false;
+                               }
+
                                if (Compiler.Settings.Version < LanguageVersion.V_3 && Initializer == null)
                                        Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented properties");
 
index 7a379fc172aff0bd375aefb7cdbee386f7e4f0c4..0c02bf0562a271da6811188fd102ecf836f0986a 100644 (file)
@@ -1272,16 +1272,38 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
+                       if (expr is ReferenceExpression && block_return_type.Kind != MemberKind.ByRef) {
+                               ec.Report.Error (8149, loc, "By-reference returns can only be used in methods that return by reference");
+                               return false;
+                       }
+
                        if (expr.Type != block_return_type && expr.Type != InternalType.ErrorType) {
-                               expr = Convert.ImplicitConversionRequired (ec, expr, block_return_type, loc);
+                               if (block_return_type.Kind == MemberKind.ByRef) {
+                                       var ref_expr = Expr as ReferenceExpression;
+                                       if (ref_expr == null) {
+                                               ec.Report.Error (8150, loc, "By-reference return is required when method returns by reference");
+                                               return false;
+                                       }
 
-                               if (expr == null) {
-                                       if (am != null && block_return_type == ec.ReturnType) {
-                                               ec.Report.Error (1662, loc,
-                                                       "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
-                                                       am.ContainerType, am.GetSignatureForError ());
+                                       var byref_return = (ReferenceContainer)block_return_type;
+
+                                       if (expr.Type != byref_return.Element) {
+                                               ec.Report.Error (8151, loc, "The return by reference expression must be of type `{0}' because this method returns by reference",
+                                                                                byref_return.GetSignatureForError ());
+                                               return false;
+                                       }
+                               } else {
+
+                                       expr = Convert.ImplicitConversionRequired (ec, expr, block_return_type, loc);
+
+                                       if (expr == null) {
+                                               if (am != null && block_return_type == ec.ReturnType) {
+                                                       ec.Report.Error (1662, loc,
+                                                               "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
+                                                               am.ContainerType, am.GetSignatureForError ());
+                                               }
+                                               return false;
                                        }
-                                       return false;
                                }
                        }
 
@@ -2185,7 +2207,7 @@ namespace Mono.CSharp {
                                }
 
                                if (type == null) {
-                                       type = type_expr.ResolveAsType (bc);
+                                       type = ResolveTypeExpression (bc);
                                        if (type == null)
                                                return false;
 
@@ -2208,6 +2230,25 @@ namespace Mono.CSharp {
                        }
 
                        if (initializer != null) {
+                               if (li.IsByRef) {
+                                       if (!(initializer is ReferenceExpression)) {
+                                               bc.Report.Error (8172, loc, "Cannot initialize a by-reference variable `{0}' with a value", li.Name);
+                                               return false;
+                                       }
+
+                                       if (bc.CurrentAnonymousMethod is AsyncInitializer) {
+                                               bc.Report.Error (8177, loc, "Async methods cannot use by-reference variables");
+                                       } else if (bc.CurrentIterator != null) {
+                                               bc.Report.Error (8176, loc, "Iterators cannot use by-reference variables");
+                                       }
+
+                               } else {
+                                       if (initializer is ReferenceExpression) {
+                                               bc.Report.Error (8171, loc, "Cannot initialize a by-value variable `{0}' with a reference expression", li.Name);
+                                               return false;
+                                       }
+                               }
+
                                initializer = ResolveInitializer (bc, li, initializer);
                                // li.Variable.DefinitelyAssigned 
                        }
@@ -2237,6 +2278,11 @@ namespace Mono.CSharp {
                        return a.ResolveStatement (bc);
                }
 
+               protected virtual TypeSpec ResolveTypeExpression (BlockContext bc)
+               {
+                       return type_expr.ResolveAsType (bc);
+               }
+
                protected override void DoEmit (EmitContext ec)
                {
                        li.CreateBuilder (ec);
@@ -2364,6 +2410,7 @@ namespace Mono.CSharp {
                        UsingVariable = 1 << 7,
                        IsLocked = 1 << 8,
                        SymbolFileHidden = 1 << 9,
+                       ByRef = 1 << 10,
 
                        ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable
                }
@@ -2448,6 +2495,8 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsByRef => (flags & Flags.ByRef) != 0;
+
                public bool IsCompilerGenerated {
                        get {
                                return (flags & Flags.CompilerGenerated) != 0;
@@ -2550,10 +2599,15 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("Already created variable `{0}'", name);
                        }
 
-                       //
-                       // All fixed variabled are pinned, a slot has to be alocated
-                       //
-                       builder = ec.DeclareLocal (Type, IsFixed);
+                       if (IsByRef) {
+                               builder = ec.DeclareLocal (ReferenceContainer.MakeType (ec.Module, Type), IsFixed);
+                       } else {
+                               //
+                               // All fixed variabled are pinned, a slot has to be alocated
+                               //
+                               builder = ec.DeclareLocal(Type, IsFixed);
+                       }
+
                        if ((flags & Flags.SymbolFileHidden) == 0)
                                ec.DefineLocalVariable (name, builder);
                }
@@ -2602,7 +2656,10 @@ namespace Mono.CSharp {
                        if ((flags & Flags.CompilerGenerated) != 0)
                                CreateBuilder (ec);
 
-                       ec.Emit (OpCodes.Ldloca, builder);
+                       if (IsByRef)
+                               ec.Emit (OpCodes.Ldloc, builder);
+                       else
+                               ec.Emit (OpCodes.Ldloca, builder);
                }
 
                public static string GetCompilerGeneratedName (Block block)
index e6ee60c585a8780e1af95af20b7941356d0a160b..0585dfd667a08d6d7f56cf247831eb915fbb7d49 100644 (file)
@@ -1991,10 +1991,11 @@ namespace Mono.CSharp
                }
        }
 
+       [System.Diagnostics.DebuggerDisplay("{DisplayDebugInfo()}")]
        class ReferenceContainer : ElementTypeSpec
        {
                ReferenceContainer (TypeSpec element)
-                       : base (MemberKind.Class, element, null)        // TODO: Kind.Class is most likely wrong
+                       : base (MemberKind.ByRef, element, null)
                {
                }
 
@@ -2004,6 +2005,11 @@ namespace Mono.CSharp
                        }
                }
 
+               string DisplayDebugInfo()
+               {
+                       return "ref " + GetSignatureForError();
+               }
+
                public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
@@ -2013,8 +2019,16 @@ namespace Mono.CSharp
                        return info;
                }
 
+               public override string GetSignatureForError ()
+               {
+                       return Element.GetSignatureForError ();
+               }
+
                public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element)
                {
+                       if (element.Kind == MemberKind.ByRef)
+                               throw new ArgumentException ();
+
                        ReferenceContainer pc;
                        if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) {
                                pc = new ReferenceContainer (element);
diff --git a/mcs/tests/test-ref-01.cs b/mcs/tests/test-ref-01.cs
new file mode 100644 (file)
index 0000000..60126a3
--- /dev/null
@@ -0,0 +1,38 @@
+// Compiler options: -unsafe
+
+public unsafe class X
+{
+       int field;
+       int* ufield;
+
+       public static void Main ()
+       {
+               int i = 5;
+               ref int j = ref i;
+
+               var x = new X ();
+               ref var v = ref x.TestMethod ();
+       }
+
+       ref int TestMethod ()
+       {
+               return ref field;
+       }
+
+       ref int TestProperty {
+               get {
+                       return ref field;
+               }
+       }
+
+       ref int this [long arg] {
+               get {
+                       return ref field;
+               }
+       }
+
+       unsafe ref int* Foo ()
+       {
+               return ref ufield;
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-ref-02.cs b/mcs/tests/test-ref-02.cs
new file mode 100644 (file)
index 0000000..9adf471
--- /dev/null
@@ -0,0 +1,35 @@
+using System;
+
+class X
+{
+       int field;
+
+       static void Main ()
+       {
+               var x = new X ();
+               x.Run ();
+       }
+
+       void Run ()
+       {
+               Test (ref this[0]);
+               Test (ref Prop);
+       }
+
+       static int Test (ref int y)
+       {
+               return y;
+       }
+
+       ref int this [int y] {
+               get {
+                       return ref field;
+               }
+       }
+
+       ref int Prop {
+               get {
+                       return ref field;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-ref-03.cs b/mcs/tests/test-ref-03.cs
new file mode 100644 (file)
index 0000000..201bd6c
--- /dev/null
@@ -0,0 +1,33 @@
+class X
+{
+       int x;
+
+       static void Main ()
+       {
+               var x = new X ();
+               Foo (ref x.Wrap (1));
+               Foo (ref x.Prop);
+               Foo (ref x[""]);                
+       }
+
+       ref int Wrap (int arg)
+       {
+               return ref x;
+       }
+
+       ref int Prop {
+               get {
+                       return ref x;
+               }
+       }
+
+       ref int this [string arg] {
+               get {
+                       return ref x;
+               }
+       }
+
+       static void Foo (ref int arg)
+       {
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-ref-04.cs b/mcs/tests/test-ref-04.cs
new file mode 100644 (file)
index 0000000..af96f23
--- /dev/null
@@ -0,0 +1,45 @@
+class X
+{
+       int field;
+
+       public static int Main ()
+       {
+               var x = new X ();
+
+               x.field = 5;
+               if (!x.Test1 ())
+                       return 1;
+
+               x.Test2 ();
+
+               if (x.Test3 ()++ != 6)
+                       return 2;
+
+               if (x.field != 7)
+                       return 3;
+
+               return 0;
+       }
+
+       bool Test1 ()
+       {
+               ref var x = ref field;
+               int v = x;
+               ++x;
+
+               return x == 6;
+       }
+
+       void Test2 ()
+       {
+               ref int x = ref field;
+               x.ToString ();
+       }
+
+       ref int Test3 ()
+       {
+               ref int l = ref field;
+               ref int v = ref l;
+               return ref l;
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-ref-05.cs b/mcs/tests/test-ref-05.cs
new file mode 100644 (file)
index 0000000..4848468
--- /dev/null
@@ -0,0 +1,46 @@
+class X
+{
+       static int field;
+
+       public static int Main ()
+       {
+               Test () = 3;
+
+               if (field != (byte) 3)
+                       return 1;
+
+               G<string>.Test (ref field) = 6;
+               if (field != 6)
+                       return 2;
+
+               --Test ();
+               if (field != 5)
+                       return 3;
+
+               Test (ref Test (), ref Test ());
+
+               return 0;
+       }
+
+       static ref int Test ()
+       {
+               return ref field;
+       }
+
+       static void Test<T> (ref T a, ref int b)
+       {
+       }
+
+       static void Test2<T> (ref T arg)
+       {
+               Test (ref arg, ref Test ());
+       }
+}
+
+class G<U>
+{
+       public static ref T Test<T> (ref T arg)
+       {
+               return ref arg;
+       }
+}
\ No newline at end of file
index db5bfbd387c5090a47e7c7e01c8813a6cec6540e..b111a7e3c5a7ecf197d9e44d133978ad86c83303 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-ref-01.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="150">
+        <size>20</size>
+      </method>
+      <method name="Int32&amp; TestMethod()" attrs="129">
+        <size>15</size>
+      </method>
+      <method name="Int32&amp; get_TestProperty()" attrs="2177">
+        <size>15</size>
+      </method>
+      <method name="Int32&amp; get_Item(Int64)" attrs="2177">
+        <size>15</size>
+      </method>
+      <method name="Int32*&amp; Foo()" attrs="129">
+        <size>15</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-ref-02.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="145">
+        <size>14</size>
+      </method>
+      <method name="Void Run()" attrs="129">
+        <size>27</size>
+      </method>
+      <method name="Int32 Test(Int32 ByRef)" attrs="145">
+        <size>11</size>
+      </method>
+      <method name="Int32&amp; get_Item(Int32)" attrs="2177">
+        <size>15</size>
+      </method>
+      <method name="Int32&amp; get_Prop()" attrs="2177">
+        <size>15</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-ref-03.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="145">
+        <size>47</size>
+      </method>
+      <method name="Int32&amp; Wrap(Int32)" attrs="129">
+        <size>15</size>
+      </method>
+      <method name="Int32&amp; get_Prop()" attrs="2177">
+        <size>15</size>
+      </method>
+      <method name="Int32&amp; get_Item(System.String)" attrs="2177">
+        <size>15</size>
+      </method>
+      <method name="Void Foo(Int32 ByRef)" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-ref-04.cs">
+    <type name="X">
+      <method name="Int32 Main()" attrs="150">
+        <size>93</size>
+      </method>
+      <method name="Boolean Test1()" attrs="129">
+        <size>30</size>
+      </method>
+      <method name="Void Test2()" attrs="129">
+        <size>22</size>
+      </method>
+      <method name="Int32&amp; Test3()" attrs="129">
+        <size>19</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
+  <test name="test-ref-05.cs">
+    <type name="X">
+      <method name="Int32 Main()" attrs="150">
+        <size>108</size>
+      </method>
+      <method name="Int32&amp; Test()" attrs="145">
+        <size>14</size>
+      </method>
+      <method name="Void Test[T](T ByRef, Int32 ByRef)" attrs="145">
+        <size>2</size>
+      </method>
+      <method name="Void Test2[T](T ByRef)" attrs="145">
+        <size>13</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="G`1[U]">
+      <method name="T&amp; Test[T](T ByRef)" attrs="150">
+        <size>10</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-static-using-01.cs">
     <type name="A.B.X">
       <method name="Int32 Test()" attrs="150">
index 713826839958b8dfb9d57f717b50dc6039e8e814..0902fb41fb84df8430700f6c918665f6e7f4e45a 100644 (file)
@@ -39,6 +39,7 @@ MONO_BTLS_SOURCES_FILES = \
 EXTRA_DIST = $(MONO_BTLS_SOURCES_FILES)
 
 CMAKE_VERBOSE=$(if $(V),VERBOSE=1,)
+NINJA_VERBOSE=$(if ($V),-v,)
 
 if NINJA
 NINJA_ARGS = -G Ninja
@@ -59,7 +60,7 @@ build-shared/$(BUILDFILE):
 
 if NINJA
 build-shared/libmono-btls-shared$(libsuffix): build-shared/$(BUILDFILE) $(MONO_BTLS_SOURCES_FILES)
-       ninja -C build-shared $(CMAKE_VERBOSE)
+       ninja -C build-shared $(NINJA_VERBOSE)
 else
 build-shared/libmono-btls-shared$(libsuffix): build-shared/$(BUILDFILE) $(MONO_BTLS_SOURCES_FILES)
        $(MAKE) -C build-shared $(CMAKE_VERBOSE)
index 2fbf826ceece5a6338eadd77b1deb9d5267801e0..8a9494054d94eaf9124c9c2731160131de14af16 100644 (file)
@@ -283,7 +283,9 @@ common_sources = \
        sre-save.c      \
        custom-attrs.c  \
        fdhandle.h      \
-       fdhandle.c
+       fdhandle.c      \
+       callspec.h      \
+       callspec.c
 
 # These source files have compile time dependencies on GC code
 gc_dependent_sources = \
diff --git a/mono/metadata/callspec.c b/mono/metadata/callspec.c
new file mode 100644 (file)
index 0000000..bf108d9
--- /dev/null
@@ -0,0 +1,348 @@
+/**
+ * \file
+ * Call specification facilities for the Mono Runtime.
+ *
+ * Author:
+ *   Paolo Molaro (lupus@ximian.com)
+ *   Dietmar Maurer (dietmar@ximian.com)
+ *
+ * (C) 2002 Ximian, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full
+ * license information.
+ */
+#include "metadata.h"
+#include "callspec.h"
+#include "assembly.h"
+#include "class-internals.h"
+#include "debug-helpers.h"
+
+static MonoAssembly *prog_assembly;
+
+gboolean
+mono_callspec_eval_exception (MonoClass *klass, MonoCallSpec *spec)
+{
+       int include = 0;
+       int i;
+
+       if (!klass)
+               return FALSE;
+
+       for (i = 0; i < spec->len; i++) {
+               MonoTraceOperation *op = &spec->ops [i];
+               int inc = 0;
+
+               switch (op->op) {
+               case MONO_TRACEOP_EXCEPTION:
+                       if (strcmp ("", op->data) == 0 &&
+                           strcmp ("all", op->data2) == 0)
+                               inc = 1;
+                       else if (strcmp ("", op->data) == 0 ||
+                                strcmp (klass->name_space, op->data) == 0)
+                               if (strcmp (klass->name, op->data2) == 0)
+                                       inc = 1;
+                       break;
+               default:
+                       break;
+               }
+               if (op->exclude) {
+                       if (inc)
+                               include = 0;
+               } else if (inc)
+                       include = 1;
+       }
+
+       return include;
+}
+
+gboolean mono_callspec_eval (MonoMethod *method, const MonoCallSpec *spec)
+{
+       int include = 0;
+       int i;
+
+       for (i = 0; i < spec->len; i++) {
+               MonoTraceOperation *op = &spec->ops[i];
+               int inc = 0;
+
+               switch (op->op) {
+               case MONO_TRACEOP_ALL:
+                       inc = 1;
+                       break;
+               case MONO_TRACEOP_PROGRAM:
+                       if (prog_assembly &&
+                           (method->klass->image ==
+                            mono_assembly_get_image (prog_assembly)))
+                               inc = 1;
+                       break;
+               case MONO_TRACEOP_WRAPPER:
+                       if ((method->wrapper_type ==
+                            MONO_WRAPPER_NATIVE_TO_MANAGED) ||
+                           (method->wrapper_type ==
+                            MONO_WRAPPER_MANAGED_TO_NATIVE))
+                               inc = 1;
+                       break;
+               case MONO_TRACEOP_METHOD:
+                       if (mono_method_desc_full_match (
+                               (MonoMethodDesc *)op->data, method))
+                               inc = 1;
+                       break;
+               case MONO_TRACEOP_CLASS:
+                       if (strcmp (method->klass->name_space, op->data) == 0)
+                               if (strcmp (method->klass->name, op->data2) ==
+                                   0)
+                                       inc = 1;
+                       break;
+               case MONO_TRACEOP_ASSEMBLY:
+                       if (strcmp (mono_image_get_name (method->klass->image),
+                                   op->data) == 0)
+                               inc = 1;
+                       break;
+               case MONO_TRACEOP_NAMESPACE:
+                       if (strcmp (method->klass->name_space, op->data) == 0)
+                               inc = 1;
+                       break;
+               case MONO_TRACEOP_EXCEPTION:
+                       break;
+               }
+               if (op->exclude) {
+                       if (inc)
+                               include = 0;
+               } else if (inc) {
+                       include = 1;
+               }
+       }
+       return include;
+}
+
+static int is_filenamechar (char p)
+{
+       if (p >= 'A' && p <= 'Z')
+               return TRUE;
+       if (p >= 'a' && p <= 'z')
+               return TRUE;
+       if (p >= '0' && p <= '9')
+               return TRUE;
+       if (p == '.' || p == ':' || p == '_' || p == '-' || p == '`')
+               return TRUE;
+       return FALSE;
+}
+
+static char *get_string (char **in)
+{
+       char *start = *in;
+       char *p = *in;
+       while (is_filenamechar (*p)) {
+               p++;
+       }
+       size_t len = p - start;
+       char *ret = (char *)g_malloc (len + 1);
+       memcpy (ret, start, len);
+       ret [len] = 0;
+       *in = p;
+       return ret;
+}
+
+enum Token {
+       TOKEN_METHOD,
+       TOKEN_CLASS,
+       TOKEN_ALL,
+       TOKEN_PROGRAM,
+       TOKEN_EXCEPTION,
+       TOKEN_NAMESPACE,
+       TOKEN_WRAPPER,
+       TOKEN_STRING,
+       TOKEN_EXCLUDE,
+       TOKEN_DISABLED,
+       TOKEN_SEPARATOR,
+       TOKEN_END,
+       TOKEN_ERROR
+};
+
+static int get_token (char **in, char **extra, char **errstr)
+{
+       char *p = *in;
+       while (p[0] == '+')
+               p++;
+
+       *extra = NULL;
+
+       if (p[0] == '\0') {
+               *in = p;
+               return TOKEN_END;
+       }
+       if (p[0] == 'M' && p[1] == ':') {
+               p += 2;
+               *extra = get_string (&p);
+               *in = p;
+               return TOKEN_METHOD;
+       }
+       if (p[0] == 'N' && p[1] == ':') {
+               p += 2;
+               *extra = get_string (&p);
+               *in = p;
+               return TOKEN_NAMESPACE;
+       }
+       if (p[0] == 'T' && p[1] == ':') {
+               p += 2;
+               *extra = get_string (&p);
+               *in = p;
+               return TOKEN_CLASS;
+       }
+       if (p[0] == 'E' && p[1] == ':') {
+               p += 2;
+               *extra = get_string (&p);
+               *in = p;
+               return TOKEN_EXCEPTION;
+       }
+       if (*p == '-') {
+               p++;
+               *in = p;
+               return TOKEN_EXCLUDE;
+       }
+       if (is_filenamechar (*p)) {
+               *extra = get_string (&p);
+               *in = p;
+               if (strcmp (*extra, "all") == 0)
+                       return TOKEN_ALL;
+               if (strcmp (*extra, "program") == 0)
+                       return TOKEN_PROGRAM;
+               if (strcmp (*extra, "wrapper") == 0)
+                       return TOKEN_WRAPPER;
+               if (strcmp (*extra, "disabled") == 0)
+                       return TOKEN_DISABLED;
+               return TOKEN_STRING;
+       }
+       if (*p == ',') {
+               p++;
+               *in = p;
+               return TOKEN_SEPARATOR;
+       }
+
+       *errstr = g_strdup_printf ("Syntax error at or around '%s'", p);
+       return TOKEN_ERROR;
+}
+
+static int get_spec (char **in, MonoCallSpec *spec, char **errstr)
+{
+       int n = spec->len;
+       char *extra = NULL;
+
+       int token = get_token (in, &extra, errstr);
+       gboolean exclude = FALSE;
+       if (token == TOKEN_EXCLUDE) {
+               exclude = TRUE;
+               token = get_token (in, &extra, errstr);
+               if (token == TOKEN_EXCLUDE || token == TOKEN_DISABLED) {
+                       *errstr = g_strdup_printf ("Expecting an expression");
+                       token = TOKEN_ERROR;
+                       goto out;
+               }
+       }
+       if (token == TOKEN_END || token == TOKEN_SEPARATOR ||
+           token == TOKEN_ERROR)
+               goto out;
+
+       if (token == TOKEN_DISABLED) {
+               spec->enabled = FALSE;
+               goto out;
+       }
+
+       if (token == TOKEN_METHOD) {
+               MonoMethodDesc *desc = mono_method_desc_new (extra, TRUE);
+               if (desc == NULL) {
+                       *errstr =
+                           g_strdup_printf ("Invalid method name: %s", extra);
+                       token = TOKEN_ERROR;
+                       goto out;
+               }
+               spec->ops[n].op = MONO_TRACEOP_METHOD;
+               spec->ops[n].data = desc;
+       } else if (token == TOKEN_ALL)
+               spec->ops[n].op = MONO_TRACEOP_ALL;
+       else if (token == TOKEN_PROGRAM)
+               spec->ops[n].op = MONO_TRACEOP_PROGRAM;
+       else if (token == TOKEN_WRAPPER)
+               spec->ops[n].op = MONO_TRACEOP_WRAPPER;
+       else if (token == TOKEN_NAMESPACE) {
+               spec->ops[n].op = MONO_TRACEOP_NAMESPACE;
+               spec->ops[n].data = g_strdup (extra);
+       } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION) {
+               char *p = strrchr (extra, '.');
+               if (p) {
+                       *p++ = 0;
+                       spec->ops[n].data = g_strdup (extra);
+                       spec->ops[n].data2 = g_strdup (p);
+               } else {
+                       spec->ops[n].data = g_strdup ("");
+                       spec->ops[n].data2 = g_strdup (extra);
+               }
+               spec->ops[n].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS
+                                                      : MONO_TRACEOP_EXCEPTION;
+       } else if (token == TOKEN_STRING) {
+               spec->ops[n].op = MONO_TRACEOP_ASSEMBLY;
+               spec->ops[n].data = g_strdup (extra);
+       } else {
+               *errstr =
+                   g_strdup_printf ("Syntax error in method specification");
+               token = TOKEN_ERROR;
+               goto out;
+       }
+
+       if (exclude)
+               spec->ops[n].exclude = 1;
+
+       spec->len = n + 1;
+       token = TOKEN_SEPARATOR;
+out:
+       if (extra != NULL) {
+               g_free (extra);
+       }
+       return token;
+}
+
+gboolean
+mono_callspec_parse (const char *options, MonoCallSpec *spec, char **errstr)
+{
+       char *p = (char *)options;
+       int size = 1;
+       int token;
+
+       memset (spec, 0, sizeof (*spec));
+       *errstr = NULL;
+
+       spec->enabled = TRUE;
+       if (*p == 0) {
+               spec->len = 1;
+               spec->ops = g_new0 (MonoTraceOperation, 1);
+               spec->ops[0].op = MONO_TRACEOP_ALL;
+               return TRUE;
+       }
+
+       for (p = (char *)options; *p != 0; p++)
+               if (*p == ',')
+                       size++;
+
+       spec->ops = g_new0 (MonoTraceOperation, size);
+
+       p = (char *)options;
+
+       while ((token = (get_spec (&p, spec, errstr))) != TOKEN_END) {
+               if (token == TOKEN_ERROR)
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+void mono_callspec_cleanup (MonoCallSpec *spec)
+{
+       if (spec->ops != NULL) {
+               g_free (spec->ops);
+       }
+       memset (spec, 0, sizeof (*spec));
+}
+
+void
+mono_callspec_set_assembly (MonoAssembly *assembly)
+{
+       prog_assembly = assembly;
+}
diff --git a/mono/metadata/callspec.h b/mono/metadata/callspec.h
new file mode 100644 (file)
index 0000000..c9f6998
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * \file
+ */
+
+#ifndef __MONO_CALLSPEC_H__
+#define __MONO_CALLSPEC_H__
+#include <glib.h>
+#include <mono/utils/mono-compiler.h>
+
+typedef enum {
+       MONO_TRACEOP_ALL,
+       MONO_TRACEOP_PROGRAM,
+       MONO_TRACEOP_METHOD,
+       MONO_TRACEOP_ASSEMBLY,
+       MONO_TRACEOP_CLASS,
+       MONO_TRACEOP_NAMESPACE,
+       MONO_TRACEOP_EXCEPTION,
+       MONO_TRACEOP_WRAPPER,
+} MonoTraceOpcode;
+
+typedef struct {
+       MonoTraceOpcode op;
+       int exclude;
+       void *data, *data2;
+} MonoTraceOperation;
+
+typedef struct {
+       int len;
+       gboolean enabled;
+       MonoTraceOperation *ops;
+} MonoCallSpec;
+
+G_BEGIN_DECLS
+
+MONO_PROFILER_API gboolean mono_callspec_parse         (const char *options,
+                                                        MonoCallSpec *spec,
+                                                        char **errstr);
+MONO_PROFILER_API void     mono_callspec_cleanup       (MonoCallSpec *spec);
+MONO_PROFILER_API gboolean mono_callspec_eval_exception        (MonoClass *klass,
+                                                        MonoCallSpec *spec);
+MONO_PROFILER_API gboolean mono_callspec_eval          (MonoMethod *method,
+                                                        const MonoCallSpec *spec);
+void                      mono_callspec_set_assembly   (MonoAssembly *assembly);
+
+G_END_DECLS
+
+#endif /* __MONO_CALLSPEC_H__ */
index e1539de106cd4bb92eaa32c27f30e5795facc6cd..da8fc30585b67fb1fa23f44a182cb0ae2ea3ce3f 100644 (file)
@@ -4955,12 +4955,19 @@ mono_class_init (MonoClass *klass)
                ghcimpl = cached_info.ghcimpl;
                has_cctor = cached_info.has_cctor;
        } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
-               /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
+               /* SZARRAY can have 3 vtable layouts, with and without the stelemref method and enum element type
                 * The first slot if for array with.
                 */
-               static int szarray_vtable_size[2] = { 0 };
+               static int szarray_vtable_size[3] = { 0 };
 
-               int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
+               int slot;
+
+               if (MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg))
+                       slot = 0;
+               else if (klass->element_class->enumtype)
+                       slot = 1;
+               else
+                       slot = 2;
 
                /* SZARRAY case */
                if (!szarray_vtable_size [slot]) {
@@ -10540,8 +10547,8 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
        if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
                MonoType *args [1];
 
-               /* generic IList, ICollection, IEnumerable */
-               interface_count = 2;
+               /* IList and IReadOnlyList -> 2x if enum*/
+               interface_count = klass->element_class->enumtype ? 4 : 2;
                interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
 
                args [0] = &klass->element_class->byval_arg;
@@ -10549,6 +10556,13 @@ mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
                        mono_defaults.generic_ilist_class, 1, args, FALSE);
                interfaces [1] = mono_class_bind_generic_parameters (
                           mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
+               if (klass->element_class->enumtype) {
+                       args [0] = mono_class_enum_basetype (klass->element_class);
+                       interfaces [2] = mono_class_bind_generic_parameters (
+                               mono_defaults.generic_ilist_class, 1, args, FALSE);
+                       interfaces [3] = mono_class_bind_generic_parameters (
+                                  mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
+               }
        } else if (mono_class_is_ginst (klass)) {
                MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
 
index a364415e2575b91e95966579e838fdb30c633f2f..dbbb646297d7850c260d5732a98a05be25753627 100644 (file)
@@ -52,6 +52,7 @@
 #include "mono/utils/mono-hwcap.h"
 #include "mono/utils/mono-logger-internals.h"
 #include "mono/metadata/w32handle.h"
+#include "mono/metadata/callspec.h"
 
 #include "mini.h"
 #include "jit.h"
@@ -1454,7 +1455,7 @@ mono_jit_parse_options (int argc, char * argv[])
                 * Need to call this before mini_init () so we can trace methods 
                 * compiled there too.
                 */
-               mono_jit_trace_calls = mono_trace_parse_options (trace_options);
+               mono_jit_trace_calls = mono_trace_set_options (trace_options);
                if (mono_jit_trace_calls == NULL)
                        exit (1);
        }
@@ -2019,7 +2020,7 @@ mono_main (int argc, char* argv[])
                 * Need to call this before mini_init () so we can trace methods 
                 * compiled there too.
                 */
-               mono_jit_trace_calls = mono_trace_parse_options (trace_options);
+               mono_jit_trace_calls = mono_trace_set_options (trace_options);
                if (mono_jit_trace_calls == NULL)
                        exit (1);
        }
@@ -2140,8 +2141,7 @@ mono_main (int argc, char* argv[])
                return 2;
        }
 
-       if (trace_options != NULL)
-               mono_trace_set_assembly (assembly);
+       mono_callspec_set_assembly (assembly);
 
        if (mono_compile_aot || action == DO_EXEC) {
                const char *error;
@@ -2400,7 +2400,7 @@ mono_jit_aot_compiling (void)
 gboolean
 mono_jit_set_trace_options (const char* options)
 {
-       MonoTraceSpec *trace_opt = mono_trace_parse_options (options);
+       MonoCallSpec *trace_opt = mono_trace_set_options (options);
        if (trace_opt == NULL)
                return FALSE;
        mono_jit_trace_calls = trace_opt;
index b5796520341be55f2ba19929cf8b695cde1a2395..30419d9178a1397dfea214d7105bf364b2f8363a 100644 (file)
@@ -3044,4 +3044,51 @@ L_3:
                                                                                                                                                           valuetype [mscorlib]System.Decimal)
                IL_0028:  ret
        }
+
+  .method private hidebysig static void  fail_inline() cil managed
+  {
+    // Code size       9 (0x9)
+    .maxstack  8
+    IL_0000:  ldc.i4.s   16
+    IL_0002:  conv.u
+    IL_0003:  ldc.i4.1
+    IL_0004:  mul.ovf.un
+    IL_0005:  localloc
+    IL_0007:  pop
+    IL_0008:  ret
+  }
+
+  .method private hidebysig static int32
+          always_inline(int32 op) cil managed aggressiveinlining
+  {
+    // Code size       24 (0x18)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  brfalse.s  IL_0009
+
+    IL_0003:  ldarg.0
+    IL_0004:  ldc.i4.2
+    IL_0005:  beq.s      IL_000b
+
+    IL_0007:  br.s       IL_000d
+
+    IL_0009:  ldc.i4.0
+    IL_000a:  ret
+
+    IL_000b:  ldc.i4.3
+    IL_000c:  ret
+
+    IL_000d:  call       void Tests::fail_inline()
+    IL_0012:  newobj     instance void [mscorlib]System.Exception::.ctor()
+    IL_0017:  throw
+  }
+
+  .method public hidebysig static int32 test_3_regress_59608() cil managed
+  {
+    .maxstack  8
+    IL_0000:  ldc.i4.2
+    IL_0001:  call       int32 Tests::always_inline(int32)
+    IL_000c:  ret
+  }
+
 }
index 3ac76cdfd8da9c4ea1327993de1364edac13c075..ce326f3c2d3443d3461073d826215663523955e4 100644 (file)
@@ -6134,9 +6134,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        prev_args = cfg->args;
        prev_arg_types = cfg->arg_types;
        prev_inlined_method = cfg->inlined_method;
-       cfg->inlined_method = cmethod;
-       cfg->ret_var_set = FALSE;
-       cfg->inline_depth ++;
+       prev_ret_var_set = cfg->ret_var_set;
        prev_real_offset = cfg->real_offset;
        prev_cbb_hash = cfg->cbb_hash;
        prev_cil_offset_to_bb = cfg->cil_offset_to_bb;
@@ -6146,9 +6144,12 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        prev_cbb = cfg->cbb;
        prev_current_method = cfg->current_method;
        prev_generic_context = cfg->generic_context;
-       prev_ret_var_set = cfg->ret_var_set;
        prev_disable_inline = cfg->disable_inline;
 
+       cfg->inlined_method = cmethod;
+       cfg->ret_var_set = FALSE;
+       cfg->inline_depth ++;
+
        if (ip && *ip == CEE_CALLVIRT && !(cmethod->flags & METHOD_ATTRIBUTE_STATIC))
                virtual_ = TRUE;
 
index af04f0bb7966ac94eb40a7e290d3ca0d2b072549..dd2e12aa9512080c4494af31cf29b4c537535ce4 100644 (file)
@@ -79,7 +79,7 @@
 #include "mini-llvm.h"
 #include "lldb.h"
 
-MonoTraceSpec *mono_jit_trace_calls;
+MonoCallSpec *mono_jit_trace_calls;
 MonoMethodDesc *mono_inject_async_exc_method;
 int mono_inject_async_exc_pos;
 MonoMethodDesc *mono_break_at_bb_method;
index f8d052627cd72c45b10e5563471039bbb43eb0b9..42a0356ef839cfc17c5bf341d1b088f247898055 100644 (file)
@@ -48,6 +48,7 @@
 #include "mono/metadata/marshal.h"
 #include "mono/metadata/security-manager.h"
 #include "mono/metadata/exception.h"
+#include "mono/metadata/callspec.h"
 
 /*
  * The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
@@ -537,9 +538,8 @@ typedef struct MonoMethodVar MonoMethodVar;
 typedef struct MonoBasicBlock MonoBasicBlock;
 typedef struct MonoLMF MonoLMF;
 typedef struct MonoSpillInfo MonoSpillInfo;
-typedef struct MonoTraceSpec MonoTraceSpec;
 
-extern MonoTraceSpec *mono_jit_trace_calls;
+extern MonoCallSpec *mono_jit_trace_calls;
 extern gboolean mono_break_on_exc;
 extern int mono_exc_esp_offset;
 extern gboolean mono_compile_aot;
@@ -2992,8 +2992,7 @@ MONO_API void      mono_debugger_run_finally             (MonoContext *start_ctx
 MONO_API gboolean mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size);
 
 /* Tracing */
-MonoTraceSpec *mono_trace_parse_options         (const char *options);
-void           mono_trace_set_assembly          (MonoAssembly *assembly);
+MonoCallSpec *mono_trace_set_options           (const char *options);
 gboolean       mono_trace_eval                  (MonoMethod *method);
 
 extern void
index 3c916a941b3ddf62af09f0ed8db444584e76c84e..0d6b19e857eb2c75b717b1d90e0ca8126c19a81f 100644 (file)
 #include <string.h>
 #include "mini.h"
 #include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/assembly.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-memory-model.h>
 #include "trace.h"
+#include <mono/metadata/callspec.h>
 
 #if defined (HOST_ANDROID) || (defined (TARGET_IOS) && defined (TARGET_IOS))
 #  undef printf
 #  define fprintf(__ignore, ...) g_log ("mono-gc", G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
 #endif
 
-static MonoTraceSpec trace_spec;
+static MonoCallSpec trace_spec;
 
 static volatile gint32 output_lock = 0;
 
-gboolean
-mono_trace_eval_exception (MonoClass *klass)
-{
-       int include = 0;
-       int i;
-
-       if (!klass)
-               return FALSE;
-
-       for (i = 0; i < trace_spec.len; i++) {
-               MonoTraceOperation *op = &trace_spec.ops [i];
-               int inc = 0;
-               
-               switch (op->op){
-               case MONO_TRACEOP_EXCEPTION:
-                       if (strcmp ("", op->data) == 0 && strcmp ("all", op->data2) == 0)
-                               inc = 1;
-                       else if (strcmp ("", op->data) == 0 || strcmp (klass->name_space, op->data) == 0)
-                               if (strcmp (klass->name, op->data2) == 0)
-                                       inc = 1;
-                       break;
-               default:
-                       break;
-               }
-               if (op->exclude){
-                       if (inc)
-                               include = 0;
-               } else if (inc)
-                       include = 1;
-       }
-
-       return include;
-}
-
-gboolean
-mono_trace_eval (MonoMethod *method)
-{
-       int include = 0;
-       int i;
-
-       for (i = 0; i < trace_spec.len; i++){
-               MonoTraceOperation *op = &trace_spec.ops [i];
-               int inc = 0;
-               
-               switch (op->op){
-               case MONO_TRACEOP_ALL:
-                       inc = 1;
-                       break;
-               case MONO_TRACEOP_PROGRAM:
-                       if (trace_spec.assembly && (method->klass->image == mono_assembly_get_image (trace_spec.assembly)))
-                               inc = 1;
-                       break;
-               case MONO_TRACEOP_WRAPPER:
-                       if ((method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) ||
-                               (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE))
-                               inc = 1;
-                       break;
-               case MONO_TRACEOP_METHOD:
-                       if (mono_method_desc_full_match ((MonoMethodDesc *) op->data, method))
-                               inc = 1;
-                       break;
-               case MONO_TRACEOP_CLASS:
-                       if (strcmp (method->klass->name_space, op->data) == 0)
-                               if (strcmp (method->klass->name, op->data2) == 0)
-                                       inc = 1;
-                       break;
-               case MONO_TRACEOP_ASSEMBLY:
-                       if (strcmp (mono_image_get_name (method->klass->image), op->data) == 0)
-                               inc = 1;
-                       break;
-               case MONO_TRACEOP_NAMESPACE:
-                       if (strcmp (method->klass->name_space, op->data) == 0)
-                               inc = 1;
-                       break;
-               case MONO_TRACEOP_EXCEPTION:
-                       break;
-               }
-               if (op->exclude) {
-                       if (inc)
-                               include = 0;
-               } else if (inc) {
-                       include = 1;
-               }
-       }
-       return include;
-}
-
-static int is_filenamechar (char p)
-{
-       if (p >= 'A' && p <= 'Z')
-               return TRUE;
-       if (p >= 'a' && p <= 'z')
-               return TRUE;
-       if (p >= '0' && p <= '9')
-               return TRUE;
-       if (p == '.' || p == ':' || p == '_' || p == '-' || p == '`')
-               return TRUE;
-       return FALSE;
-}
-
-static char *input;
-static char *value;
-
-static void get_string (void)
+gboolean mono_trace_eval_exception (MonoClass *klass)
 {
-       char *start = input;
-       while (is_filenamechar (*input)){
-               input++;
-       }
-       if (value != NULL)
-               g_free (value);
-       size_t len = input - start;
-       value = (char *)g_malloc (len + 1);
-       memcpy (value, start, len);
-       value [len] = 0;
+       return mono_callspec_eval_exception (klass, &trace_spec);
 }
 
-enum Token {
-       TOKEN_METHOD,
-       TOKEN_CLASS,
-       TOKEN_ALL,
-       TOKEN_PROGRAM,
-       TOKEN_EXCEPTION,
-       TOKEN_NAMESPACE,
-       TOKEN_WRAPPER,
-       TOKEN_STRING,
-       TOKEN_EXCLUDE,
-       TOKEN_DISABLED,
-       TOKEN_SEPARATOR,
-       TOKEN_END,
-       TOKEN_ERROR
-};
-
-static int
-get_token (void)
+gboolean mono_trace_eval (MonoMethod *method)
 {
-       while (input [0] == '+')
-               input++;
-
-       if (input [0] == '\0') {
-               return TOKEN_END;
-       }
-       if (input [0] == 'M' && input [1] == ':'){
-               input += 2;
-               get_string ();
-               return TOKEN_METHOD;
-       }
-       if (input [0] == 'N' && input [1] == ':'){
-               input += 2;
-               get_string ();
-               return TOKEN_NAMESPACE;
-       }
-       if (input [0] == 'T' && input [1] == ':'){
-               input += 2;
-               get_string ();
-               return TOKEN_CLASS;
-       }
-       if (input [0] == 'E' && input [1] == ':'){
-               input += 2;
-               get_string ();
-               return TOKEN_EXCEPTION;
-       }
-       if (*input == '-'){
-               input++;
-               return TOKEN_EXCLUDE;
-       }
-       if (is_filenamechar (*input)){
-               get_string ();
-               if (strcmp (value, "all") == 0)
-                       return TOKEN_ALL;
-               if (strcmp (value, "program") == 0)
-                       return TOKEN_PROGRAM;
-               if (strcmp (value, "wrapper") == 0)
-                       return TOKEN_WRAPPER;
-               if (strcmp (value, "disabled") == 0)
-                       return TOKEN_DISABLED;
-               return TOKEN_STRING;
-       }
-       if (*input == ','){
-               input++;
-               return TOKEN_SEPARATOR;
-       }
-
-       fprintf (stderr, "Syntax error at or around '%s'\n", input);    
-       return TOKEN_ERROR;
+       return mono_callspec_eval (method, &trace_spec);
 }
 
-static void
-cleanup (void)
+MonoCallSpec *mono_trace_set_options (const char *options)
 {
-       if (value != NULL)
-               g_free (value);
-}
-
-static int
-get_spec (int *last)
-{
-       int token = get_token ();
-       if (token == TOKEN_EXCLUDE){
-               token = get_spec (last);
-               if (token == TOKEN_EXCLUDE){
-                       fprintf (stderr, "Expecting an expression");
-                       return TOKEN_ERROR;
-               }
-               if (token == TOKEN_ERROR)
-                       return token;
-               trace_spec.ops [(*last)-1].exclude = 1;
-               return TOKEN_SEPARATOR;
-       }
-       if (token == TOKEN_END || token == TOKEN_SEPARATOR || token == TOKEN_ERROR)
-               return token;
-       
-       if (token == TOKEN_METHOD){
-               MonoMethodDesc *desc = mono_method_desc_new (value, TRUE);
-               if (desc == NULL){
-                       fprintf (stderr, "Invalid method name: %s\n", value);
-                       return TOKEN_ERROR;
-               }
-               trace_spec.ops [*last].op = MONO_TRACEOP_METHOD;
-               trace_spec.ops [*last].data = desc;
-       } else if (token == TOKEN_ALL)
-               trace_spec.ops [*last].op = MONO_TRACEOP_ALL;
-       else if (token == TOKEN_PROGRAM)
-               trace_spec.ops [*last].op = MONO_TRACEOP_PROGRAM;
-       else if (token == TOKEN_WRAPPER)
-               trace_spec.ops [*last].op = MONO_TRACEOP_WRAPPER;
-       else if (token == TOKEN_NAMESPACE){
-               trace_spec.ops [*last].op = MONO_TRACEOP_NAMESPACE;
-               trace_spec.ops [*last].data = g_strdup (value);
-       } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION){
-               char *p = strrchr (value, '.');
-               if (p) {
-                       *p++ = 0;
-                       trace_spec.ops [*last].data = g_strdup (value);
-                       trace_spec.ops [*last].data2 = g_strdup (p);
-               }
-               else {
-                       trace_spec.ops [*last].data = g_strdup ("");
-                       trace_spec.ops [*last].data2 = g_strdup (value);
-               }
-               trace_spec.ops [*last].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS : MONO_TRACEOP_EXCEPTION;
-       } else if (token == TOKEN_STRING){
-               trace_spec.ops [*last].op = MONO_TRACEOP_ASSEMBLY;
-               trace_spec.ops [*last].data = g_strdup (value);
-       } else if (token == TOKEN_DISABLED) {
-               trace_spec.enabled = FALSE;
-       } else {
-               fprintf (stderr, "Syntax error in trace option specification\n");
-               return TOKEN_ERROR;
+       char *errstr;
+       if (!mono_callspec_parse (options, &trace_spec, &errstr)) {
+               fprintf (stderr, "%s\n", errstr);
+               g_free (errstr);
+               return NULL;
        }
-       (*last)++;
-       return TOKEN_SEPARATOR;
-}
 
-MonoTraceSpec *
-mono_trace_parse_options (const char *options)
-{
-       char *p = (char*)options;
-       int size = 1;
-       int last_used;
-       int token;
-
-       trace_spec.enabled = TRUE;
-       if (*p == 0){
-               trace_spec.len = 1;
-               trace_spec.ops = g_new0 (MonoTraceOperation, 1);
-               trace_spec.ops [0].op = MONO_TRACEOP_ALL;
-               return &trace_spec;
-       }
-               
-       for (p = (char*)options; *p != 0; p++)
-               if (*p == ',')
-                       size++;
-       
-       trace_spec.ops = g_new0 (MonoTraceOperation, size);
-
-       input = (char*)options;
-       last_used = 0;
-       
-       while ((token = (get_spec (&last_used))) != TOKEN_END){
-               if (token == TOKEN_ERROR)
-                       return NULL;
-               if (token == TOKEN_SEPARATOR)
-                       continue;
-       }
-       trace_spec.len = last_used;
-       cleanup ();
        return &trace_spec;
 }
 
-void
-mono_trace_set_assembly (MonoAssembly *assembly)
-{
-       trace_spec.assembly = assembly;
-}
-
 static
 #ifdef HAVE_KW_THREAD
 __thread 
index 7f6d4562f7d4a1cbcddd01128fa5981618ff1fae..516fd8c60f712170ec1808f32239231107dd1f84 100644 (file)
@@ -7,31 +7,6 @@
 #include <glib.h>
 #include "mono/utils/mono-compiler.h"
 
-typedef enum {
-       MONO_TRACEOP_ALL,
-       MONO_TRACEOP_PROGRAM,
-       MONO_TRACEOP_METHOD,
-       MONO_TRACEOP_ASSEMBLY,
-       MONO_TRACEOP_CLASS,
-       MONO_TRACEOP_NAMESPACE,
-       MONO_TRACEOP_EXCEPTION,
-       MONO_TRACEOP_WRAPPER,
-} MonoTraceOpcode;
-
-typedef struct {
-       MonoTraceOpcode op;
-       int   exclude;
-       void *data, *data2;
-} MonoTraceOperation;
-
-struct MonoTraceSpec {
-       int len;
-       gboolean enabled;
-       MonoTraceOperation *ops;
-
-       MonoAssembly *assembly;
-};
-
 G_BEGIN_DECLS
 
 void
index 3cfadd1e5138ba73a8edc41cd0d618dceb975a53..b20444f31db4fc324d731d8c6a3d15301627bca8 100644 (file)
@@ -104,6 +104,24 @@ parse_arg (const char *arg, ProfilerConfig *config)
        } else if (match_option (arg, "calldepth", &val)) {
                char *end;
                config->max_call_depth = strtoul (val, &end, 10);
+       } else if (match_option (arg, "callspec", &val)) {
+               if (!val)
+                       val = "";
+               if (val[0] == '\"')
+                       ++val;
+               char *spec = g_strdup (val);
+               size_t speclen = strlen (val);
+               if (speclen > 0 && spec[speclen - 1] == '\"')
+                       spec[speclen - 1] = '\0';
+               char *errstr;
+               if (!mono_callspec_parse (spec, &config->callspec, &errstr)) {
+                       mono_profiler_printf_err (
+                           "Could not parse callspec: '%s': %s", spec,
+                           errstr);
+                       g_free (errstr);
+                       mono_callspec_cleanup (&config->callspec);
+               }
+               g_free (spec);
        } else if (match_option (arg, "covfilter-file", &val)) {
                if (config->cov_filter_files == NULL)
                        config->cov_filter_files = g_ptr_array_new ();
index f3dbc56cbad61ad5382d149c07877bdd0359877b..8a677c2720d48bba530592351a5f6283d87f970b 100644 (file)
@@ -1816,6 +1816,10 @@ method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
 static MonoProfilerCallInstrumentationFlags
 method_filter (MonoProfiler *prof, MonoMethod *method)
 {
+       if (log_config.callspec.len > 0 &&
+           !mono_callspec_eval (method, &log_config.callspec))
+               return MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
+
        return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
               MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE |
               MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL |
index f0503e4a4e423f7c9bc43c131d9ba5a3d3537642..e381d8975471a34d1895b98bb0f05b07a54db502 100644 (file)
@@ -4,6 +4,7 @@
 #include <glib.h>
 #define MONO_PROFILER_UNSTABLE_GC_ROOTS
 #include <mono/metadata/profiler.h>
+#include <mono/metadata/callspec.h>
 
 #define BUF_ID 0x4D504C01
 #define LOG_HEADER_ID 0x4D505A01
@@ -537,6 +538,9 @@ typedef struct {
 
        // Sample mode. Only used at startup.
        MonoProfilerSampleMode sampling_mode;
+
+       // Callspec config - which methods are to be instrumented
+       MonoCallSpec callspec;
 } ProfilerConfig;
 
 void proflog_parse_args (ProfilerConfig *config, const char *desc);
index b0e9d47ff1e778425504e95dfd9e0c8307341fd6..7b3a68247a8f16df2176a2622b2b58b6a91615af 100644 (file)
@@ -1,14 +1,10 @@
 using System;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
 public class Test {
 
-       static void puts (string s)
-       {
-               Console.WriteLine (s);
-       }
-
-       public static int jagged ()
+       public static int test_0_jagged ()
        {
                int[][] j2 = new int [3][];
 
@@ -32,7 +28,7 @@ public class Test {
                return 0;
        }
 
-       public static int stest ()
+       public static int test_0_stest ()
        {
                string[] sa = new string[32];
 
@@ -44,13 +40,13 @@ public class Test {
 
                for (int i = 0; i < sa.Length; i++){
                        if (sa [i] != null)
-                               puts (sa [i]);
+                               Console.WriteLine (sa [i]);
                }
                
                return 0;
        }
        
-       public static int atest2 ()
+       public static int test_0_atest2 ()
        {
                int[,] ia = new int[32,32];
 
@@ -71,7 +67,7 @@ public class Test {
                return 0;
        }
        
-       public static int atest ()
+       public static int test_0_atest ()
        {
                int[] ia = new int[32];
 
@@ -93,35 +89,51 @@ public class Test {
 
                for (int i = 0; i <ia.Length; i++)
                        if ((int)ia.GetValue (i) != i*i*i){
-                               puts ("Crap: " + i + " " + (int) ia.GetValue (i) );
+                               Console.WriteLine ("Crap: " + i + " " + (int) ia.GetValue (i) );
 
                                return 4;
                        }
                
                return 0;
        }
-       
 
-       public static int Main () {
-               puts ("a");
-               if (atest () != 0)
-                       return atest ();
-               puts ("b");     
-               if (atest2 () != 0)
-                       return 1;
-               puts ("c");
-               if (atest2 () != 0)
-                       return 1;
-               puts ("d");     
-               if (stest () != 0)
+       enum Foo { a, b };
+       public static int test_0_enum_array_casting () {
+        var x = new Foo[10];
+               try {
+                       var y = (IReadOnlyList<int>)(object)x;
+               } catch (Exception e) {
                        return 1;
-               puts ("e");     
-               if (jagged () != 0)
-                       return 1;
-               
-               
+               }
+               try {
+                       var y = (IList<int>)(object)x;
+               } catch (Exception e) {
+                       return 2;
+               }
+
+               try {
+                       var y = (ICollection<int>)(object)x;
+               } catch (Exception e) {
+                       return 3;
+               }
+
+               try {
+                       var y = (IEnumerable<int>)(object)x;
+               } catch (Exception e) {
+                       return 4;
+               }
+
+               try {
+                       var y = (IReadOnlyCollection<int>)(object)x;
+               } catch (Exception e) {
+                       return 5;
+               }
                return 0;
        }
+
+       public static int Main (string[] args) {
+               return TestDriver.RunTests (typeof (Test), args);
+       }
 }
 
 
index d2e5ad512cd78a353af0e1e05eb4308b9bd287b6..84c3083b3a1a631d0557de98411a83a1334366d9 100644 (file)
@@ -23,6 +23,7 @@
     <ClCompile Include="..\mono\metadata\assembly.c" />\r
     <ClCompile Include="..\mono\metadata\attach.c" />\r
     <ClCompile Include="..\mono\metadata\boehm-gc.c" />\r
+    <ClCompile Include="..\mono\metadata\callspec.c" />\r
     <ClCompile Include="..\mono\metadata\class-accessors.c" />\r
     <ClCompile Include="..\mono\metadata\class.c" />\r
     <ClCompile Include="..\mono\metadata\cominterop.c" />\r
     <ClInclude Include="..\mono\metadata\appdomain-icalls.h" />\r
     <ClInclude Include="..\mono\metadata\assembly.h" />\r
     <ClInclude Include="..\mono\metadata\attach.h" />\r
+    <ClInclude Include="..\mono\metadata\callspec.h" />\r
     <ClInclude Include="..\mono\metadata\cil-coff.h" />\r
     <ClInclude Include="..\mono\metadata\class-internals.h" />\r
     <ClInclude Include="..\mono\metadata\class.h" />\r
index 9b504614ac0ddbb600f3f989782fae4e8b7acfc5..3ad4c05c8008d4f72cccf410e22233ea2e7dd7a0 100755 (executable)
@@ -100,7 +100,7 @@ class MonoReleaseProfile(DarwinProfile):
         self.env.set('PANGO_SYSCONFDIR', '%{staged_prefix}/etc')
         self.env.set('PANGO_LIBDIR', '%{staged_prefix}/lib')
         # self.env.set ('MONO_PATH', '%{staged_prefix}/lib/mono/4.0')
-        self.debug_info = ['gtk+', 'cairo',
+        self.debug_info = ['gtk+', 'cairo', 'glib',
                            'pango', 'mono', 'llvm', 'libgdiplus']
         self.cache_host = None
 
@@ -396,4 +396,4 @@ class MonoReleaseProfile(DarwinProfile):
 
         subprocess.call(['bash', '-c', path])
 
-MonoReleaseProfile()
\ No newline at end of file
+MonoReleaseProfile()
index 8f127d7c414caa748fc8ed8349ce65d253645230..5d23ed09d2c7b4e5d8be99dcc111471d9a0d3ff4 100644 (file)
@@ -6,7 +6,7 @@ class MonoExtensionsPackage(Package):
     def __init__(self):
         Package.__init__(self, 'mono-extensions', None,
                          sources=['git@github.com:xamarin/mono-extensions.git'],
-                         revision='07ad37d63e0e9dcf7c879a72bc14c5d6c794f7b6'
+                         revision='3cc5e2e1870b35f15b1540f835a370d2b011bacd'
                          )
         self.source_dir_name = 'mono-extensions'
 
index f600c3ace39acb3db11090fee9c33d3e3de325c8..6fdb428d7dd4b000bf49e05c09c28d3b2a54cfae 100755 (executable)
@@ -3,10 +3,11 @@
 # This script is meant to be executed on all "slave" machines that run coverage collection.
 
 COV_DIR=coverage
-COV_INFO="$COV_DIR/$JOB_NAME.info"
+COV_NAME="$(echo $JOB_NAME | sed 's#/#-#g').info"
+COV_INFO="$COV_DIR/$COV_NAME"
 
 # Build Mono and collect coverage on the test suite.
-CI_TAGS=collect-coverage,monolite scripts/ci/run-jenkins.sh
+CI_TAGS="collect-coverage,monolite,$CI_TAGS" scripts/ci/run-jenkins.sh
 
 # Place the coverage info file into the coverage directory.
 # Multiple such files can be assembled to create a unified coverage report that spans multiple architectures and operating systems.
@@ -14,7 +15,7 @@ mkdir "$COV_DIR"
 scripts/ci/run-step.sh --label=coverage-lcov --timeout=20m lcov --no-external -c -d mono -d support -d tools -o "$COV_INFO"
 
 # Generate HTML coverage report in the lcov directory at the root of the project.
-scripts/ci/run-step.sh --label=coverage-genhtml --timeout=20m genhtml "$COV_INFO" -o lcov
+scripts/ci/run-step.sh --label=coverage-genhtml --timeout=20m genhtml -f -s "$COV_INFO" -o lcov
 
 # Make the paths relative so that they could be assembled from different Jenkins workspaces.
 sed -Eie "s#^SF:$WORKSPACE/?#SF:#" "$COV_INFO"
index bdecfae3efb974b15ed2b08a787f2b04716aa4ab..ca0cca115eb2ac8fd889b4583b32d02727074133 100755 (executable)
@@ -10,23 +10,25 @@ make_timeout=300m
 if [[ $CI_TAGS == *'collect-coverage'* ]]; then
     # Collect coverage for further use by lcov and similar tools.
     # Coverage must be collected with -O0 and debug information.
-    export CFLAGS="-ggdb3 --coverage -O0"
-    # Collect coverage on all optimizations
-    export MONO_ENV_OPTIONS="$MONO_ENV_OPTIONS -O=all"
-elif [[ ${CI_TAGS} == *'clang-sanitizer'* ]]; then
+    export CFLAGS="$CFLAGS -ggdb3 --coverage -O0"
+fi
+
+if [[ ${CI_TAGS} == *'clang-sanitizer'* ]]; then
        export CC="clang"
        export CXX="clang++"
-       export CFLAGS="-g -O1 -fsanitize=thread -fsanitize-blacklist=${MONO_REPO_ROOT}/scripts/ci/clang-thread-sanitizer-blacklist -mllvm -tsan-instrument-atomics=false"
+       export CFLAGS="$CFLAGS -g -O1 -fsanitize=thread -fsanitize-blacklist=${MONO_REPO_ROOT}/scripts/ci/clang-thread-sanitizer-blacklist -mllvm -tsan-instrument-atomics=false"
        export LDFLAGS="-fsanitize=thread"
        # TSAN_OPTIONS are used by programs that were compiled with Clang's ThreadSanitizer
        # see https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags for more details
        export TSAN_OPTIONS="history_size=7:exitcode=0:force_seq_cst_atomics=1"
        make_timeout=30m
-elif [[ ${label} == w* ]]; then
+fi
+
+if [[ ${label} == w* ]]; then
     # Passing -ggdb3 on Cygwin breaks linking against libmonosgen-x.y.dll
-    export CFLAGS="-g -O2"
+    export CFLAGS="$CFLAGS -g -O2"
 else
-    export CFLAGS="-ggdb3 -O2"
+    export CFLAGS="$CFLAGS -ggdb3 -O2"
 fi
 
 if [[ $CI_TAGS == *'retry-flaky-tests'* ]]; then
@@ -108,6 +110,8 @@ ${TESTCMD} --label=make --timeout=${make_timeout} --fatal make ${make_parallelis
 if [[ ${CI_TAGS} == *'checked-coop'* ]]; then export MONO_CHECK_MODE=gc,thread; fi
 if [[ ${CI_TAGS} == *'checked-all'* ]]; then export MONO_CHECK_MODE=all; fi
 
+export MONO_ENV_OPTIONS="$MONO_ENV_OPTIONS $MONO_TEST_ENV_OPTIONS"
+
 if [[ ${CI_TAGS} == *'acceptance-tests'* ]];
     then
        $(dirname "${BASH_SOURCE[0]}")/run-test-acceptance-tests.sh