[mcs] Report more unsafe code errors in iterators. Fixes #56616
authorMarek Safar <marek.safar@gmail.com>
Fri, 19 May 2017 16:43:59 +0000 (18:43 +0200)
committerMarek Safar <marek.safar@gmail.com>
Fri, 19 May 2017 16:46:14 +0000 (18:46 +0200)
mcs/errors/cs1629-3.cs [new file with mode: 0644]
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/iterators.cs
mcs/mcs/statement.cs

diff --git a/mcs/errors/cs1629-3.cs b/mcs/errors/cs1629-3.cs
new file mode 100644 (file)
index 0000000..f7ceed6
--- /dev/null
@@ -0,0 +1,19 @@
+// CS1629: Unsafe code may not appear in iterators
+// Line: 17
+// Compiler options: -unsafe
+
+using System.Collections.Generic;
+
+public unsafe class TestClass
+{
+       public struct Foo {
+               public bool C;
+       }
+
+       Foo *current;
+
+       public IEnumerable<Foo> EnumeratorCurrentEvents ()
+       {
+               yield return *current;
+       }
+}
\ No newline at end of file
index d2a1b7e95dad11d133df17ce8bafb86896bc3567..82e86649ca65432646dd1b9e946f7dc9d005eb64 100644 (file)
@@ -1130,6 +1130,16 @@ namespace Mono.CSharp {
                        Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
                }
 
+               public static void UnsafeInsideIteratorError (ResolveContext rc, Location loc)
+               {
+                       UnsafeInsideIteratorError (rc.Report, loc);
+               }
+
+               public static void UnsafeInsideIteratorError (Report report, Location loc)
+               {
+                       report.Error (1629, loc, "Unsafe code may not appear in iterators");
+               }
+
                //
                // Converts `source' to an int, uint, long or ulong.
                //
@@ -3456,8 +3466,12 @@ namespace Mono.CSharp {
                                CheckProtectedMemberAccess (rc, member);
                        }
 
-                       if (member.MemberType.IsPointer && !rc.IsUnsafe) {
-                               UnsafeError (rc, loc);
+                       if (member.MemberType.IsPointer) {
+                               if (rc.CurrentIterator != null) {
+                                       UnsafeInsideIteratorError (rc, loc);
+                               } else if (!rc.IsUnsafe) {
+                                       UnsafeError (rc, loc);
+                               }
                        }
 
                        var dep = member.GetMissingDependencies ();
@@ -6075,8 +6089,12 @@ namespace Mono.CSharp {
                                arg_count++;
                        }
 
-                       if (has_unsafe_arg && !ec.IsUnsafe) {
-                               Expression.UnsafeError (ec, loc);
+                       if (has_unsafe_arg) {
+                               if (ec.CurrentIterator != null) {
+                                       Expression.UnsafeInsideIteratorError (ec, loc);
+                               } else if (!ec.IsUnsafe) {
+                                       Expression.UnsafeError (ec, loc);
+                               }
                        }
 
                        //
index c7747f014fdee5da31e0b772c45dbdaa148c769c..c054330db202f339be76b7a07f01626fd207f7fe 100644 (file)
@@ -718,8 +718,11 @@ namespace Mono.CSharp
 
                Expression ResolveAddressOf (ResolveContext ec)
                {
-                       if (!ec.IsUnsafe)
+                       if (ec.CurrentIterator != null) {
+                               UnsafeInsideIteratorError (ec, loc);
+                       } else if (!ec.IsUnsafe) {
                                UnsafeError (ec, loc);
+                       }
 
                        Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
                        if (Expr == null || Expr.eclass != ExprClass.Variable) {
@@ -737,7 +740,7 @@ namespace Mono.CSharp
                                is_fixed = vr.IsFixed;
                                vr.SetHasAddressTaken ();
 
-                               if (vr.IsHoisted) {
+                               if (vr.IsHoisted && ec.CurrentIterator == null) {
                                        AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc);
                                }
                        } else {
@@ -984,8 +987,11 @@ namespace Mono.CSharp
                        if (expr == null)
                                return null;
 
-                       if (!ec.IsUnsafe)
+                       if (ec.CurrentIterator != null) {
+                               UnsafeInsideIteratorError (ec, loc);
+                       } else if (!ec.IsUnsafe) {
                                UnsafeError (ec, loc);
+                       }
 
                        var pc = expr.Type as PointerContainer;
 
@@ -2453,8 +2459,12 @@ namespace Mono.CSharp
                                return null;
                        }
 
-                       if (type.IsPointer && !ec.IsUnsafe) {
-                               UnsafeError (ec, loc);
+                       if (type.IsPointer) {
+                               if (ec.CurrentIterator != null) {
+                                       UnsafeInsideIteratorError (ec, loc);
+                               } else if (!ec.IsUnsafe) {
+                                       UnsafeError (ec, loc);
+                               }
                        }
 
                        eclass = ExprClass.Value;
@@ -10485,8 +10495,12 @@ namespace Mono.CSharp
                        }
 
                        type = ac.Element;
-                       if (type.IsPointer && !ec.IsUnsafe) {
-                               UnsafeError (ec, ea.Location);
+                       if (type.IsPointer) {
+                               if (ec.CurrentIterator != null) {
+                                       UnsafeInsideIteratorError (ec, ea.Location);
+                               } else if (!ec.IsUnsafe) {
+                                       UnsafeError (ec, ea.Location);
+                               }
                        }
 
                        if (conditional_access_receiver)
@@ -11404,7 +11418,10 @@ namespace Mono.CSharp
                                if (!(ec.CurrentMemberDefinition is Field) && !TypeManager.VerifyUnmanaged (ec.Module, type, loc))
                                        return null;
 
-                               if (!ec.IsUnsafe) {
+                               var rc = ec as ResolveContext;
+                               if (rc?.CurrentIterator != null) {
+                                       UnsafeInsideIteratorError (ec.Module.Compiler.Report, loc);
+                               } else if (!ec.IsUnsafe) {
                                        UnsafeError (ec.Module.Compiler.Report, loc);
                                }
 
index 0b6fc1abf7722452569bed9c6c1ae75ac2815296..3afe93ce5ffe1bf89df1833938932a96f7abb294 100644 (file)
@@ -1220,7 +1220,7 @@ namespace Mono.CSharp
                        }
 
                        if ((modifiers & Modifiers.UNSAFE) != 0) {
-                               parent.Compiler.Report.Error (1629, method.Location, "Unsafe code may not appear in iterators");
+                               Expression.UnsafeInsideIteratorError (parent.Compiler.Report, method.Location);
                        }
 
                        method.Block = method.Block.ConvertToIterator (method, parent, iterator_type, is_enumerable);
index 4f67eb3240f38407e24a36fc3c384b3f60714489..20eb19e6cee8b4fb54b7df5d9ff4e57338f1a680 100644 (file)
@@ -6357,7 +6357,7 @@ namespace Mono.CSharp {
                public override bool Resolve (BlockContext ec)
                {
                        if (ec.CurrentIterator != null)
-                               ec.Report.Error (1629, loc, "Unsafe code may not appear in iterators");
+                               Expression.UnsafeInsideIteratorError (ec, loc);
 
                        using (ec.Set (ResolveContext.Options.UnsafeScope))
                                return Block.Resolve (ec);