Merge pull request #949 from ermshiperete/bug-novell-463149
[mono.git] / mcs / mcs / nullable.cs
index 4b677e11888787e71e65123a107a385722e1c464..44abde0c13afd7ebd140986849ee77bada4d7b68 100644 (file)
@@ -529,6 +529,11 @@ namespace Mono.CSharp.Nullable
                                return null;
 
                        Expression res = base.ResolveOperator (ec, unwrap);
+                       if (res == null) {
+                               Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), Expr.Type);
+                               return null;
+                       }
+
                        if (res != this) {
                                if (user_operator == null)
                                        return res;
@@ -659,10 +664,10 @@ namespace Mono.CSharp.Nullable
                {
                        if (rc.IsRuntimeBinder) {
                                if (UnwrapLeft == null && !Left.Type.IsNullableType)
-                                       Left = Wrap.Create (Left, rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { Left.Type }));
+                                       Left = LiftOperand (rc, Left);
 
                                if (UnwrapRight == null && !Right.Type.IsNullableType)
-                                       Right = Wrap.Create (Right, rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { Right.Type }));
+                                       Right = LiftOperand (rc, Right);
                        } else {
                                if (UnwrapLeft == null && Left != null && Left.Type.IsNullableType) {
                                        Left = Unwrap.CreateUnwrapped (Left);
@@ -681,6 +686,21 @@ namespace Mono.CSharp.Nullable
                        return this;
                }
 
+               Expression LiftOperand (ResolveContext rc, Expression expr)
+               {
+                       TypeSpec type;
+                       if (expr.IsNull) {
+                               type = Left.IsNull ? Right.Type : Left.Type;
+                       } else {
+                               type = expr.Type;
+                       }
+
+                       if (!type.IsNullableType)
+                               type = rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { type });
+
+                       return Wrap.Create (expr, type);
+               }
+
                public override void Emit (EmitContext ec)
                {
                        if (IsBitwiseBoolean && UserOperator == null) {
@@ -762,6 +782,9 @@ namespace Mono.CSharp.Nullable
                                if (ec.HasSet (BuilderContext.Options.AsyncBody) && Binary.Right.ContainsEmitWithAwait ()) {
                                        Left = Left.EmitToField (ec);
                                        Right = Right.EmitToField (ec);
+                               } else {
+                                       UnwrapLeft.Store (ec);
+                                       UnwrapRight.Store (ec);
                                }
 
                                Left.Emit (ec);
@@ -1239,7 +1262,9 @@ namespace Mono.CSharp.Nullable
                public override void FlowAnalysis (FlowAnalysisContext fc)
                {
                        left.FlowAnalysis (fc);
+                       var left_da = fc.BranchDefiniteAssignment ();
                        right.FlowAnalysis (fc);
+                       fc.DefiniteAssignment = left_da;
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)