Merge branch 'master' into msbuilddll2
[mono.git] / mcs / mcs / ecore.cs
index f01a1486bd5c8ea102b9fd11875bfa9a14184675..ec0d7a2c60670ce1f4f3caea3dafab0ad30461a8 100644 (file)
@@ -712,13 +712,20 @@ namespace Mono.CSharp {
                {
                        var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
                        if (ctors == null) {
-                               rc.Report.SymbolRelatedToPreviousError (type);
-                               if (type.IsStruct) {
+                               switch (type.Kind) {
+                               case MemberKind.Struct:
+                                       rc.Report.SymbolRelatedToPreviousError (type);
                                        // Report meaningful error for struct as they always have default ctor in C# context
                                        OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
-                               } else {
+                                       break;
+                               case MemberKind.MissingType:
+                               case MemberKind.InternalCompilerType:
+                                       break;
+                               default:
+                                       rc.Report.SymbolRelatedToPreviousError (type);
                                        rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
                                                type.GetSignatureForError ());
+                                       break;
                                }
 
                                return null;
@@ -923,6 +930,10 @@ namespace Mono.CSharp {
                        ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
                }
 
+               public virtual void FlowAnalysis (FlowAnalysisContext fc)
+               {
+               }
+
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -1175,6 +1186,10 @@ namespace Mono.CSharp {
        /// </summary>
        public abstract class ExpressionStatement : Expression
        {
+               public virtual void MarkReachable (Reachability rc)
+               {
+               }
+
                public ExpressionStatement ResolveStatement (BlockContext ec)
                {
                        Expression e = Resolve (ec);
@@ -1182,7 +1197,7 @@ namespace Mono.CSharp {
                                return null;
 
                        ExpressionStatement es = e as ExpressionStatement;
-                       if (es == null)
+                       if (es == null || e is AnonymousMethodBody)
                                Error_InvalidExpressionStatement (ec);
 
                        //
@@ -1310,6 +1325,11 @@ namespace Mono.CSharp {
                        child.Emit (ec);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       child.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
 #if STATIC
@@ -2141,6 +2161,11 @@ namespace Mono.CSharp {
                        {
                                stm.EmitStatement (ec);
                        }
+
+                       public override void FlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               stm.FlowAnalysis (fc);
+                       }
                }
 
                readonly Expression expr, orig_expr;
@@ -2244,6 +2269,11 @@ namespace Mono.CSharp {
                        expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        return orig_expr.MakeExpression (ctx);
@@ -2339,7 +2369,38 @@ namespace Mono.CSharp {
                {
                        throw new InternalErrorException ("Missing Resolve call");
                }
+       }
+
+       public class UnreachableExpression : Expression
+       {
+               public UnreachableExpression (Expression expr)
+               {
+                       this.loc = expr.Location;
+               }
 
+               public override Expression CreateExpressionTree (ResolveContext ec)
+               {
+                       // TODO: is it ok
+                       throw new NotImplementedException ();
+               }
+
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       fc.Report.Warning (429, 4, loc, "Unreachable expression code detected");
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
+               {
+               }
        }
 
        //
@@ -2470,14 +2531,7 @@ namespace Mono.CSharp {
 
                protected override Expression DoResolve (ResolveContext rc)
                {
-                       var e = SimpleNameResolve (rc, null);
-
-                       var fe = e as FieldExpr;
-                       if (fe != null) {
-                               fe.VerifyAssignedStructField (rc, null);
-                       }
-
-                       return e;
+                       return SimpleNameResolve (rc, null);
                }
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
@@ -3162,6 +3216,12 @@ namespace Mono.CSharp {
                                member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (InstanceExpression != null)
+                               InstanceExpression.FlowAnalysis (fc);
+               }
+
                public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs)
                {
                        if (!ResolveInstanceExpressionCore (rc, rhs))
@@ -3264,15 +3324,7 @@ namespace Mono.CSharp {
                                                DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
                                }
 
-                               InstanceExpression = new This (loc);
-                               if (this is FieldExpr && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
-                                       using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
-                                               InstanceExpression = InstanceExpression.Resolve (rc);
-                                       }
-                               } else {
-                                       InstanceExpression = InstanceExpression.Resolve (rc);
-                               }
-
+                               InstanceExpression = new This (loc).Resolve (rc);
                                return false;
                        }
 
@@ -3280,29 +3332,17 @@ namespace Mono.CSharp {
                        if (me != null) {
                                me.ResolveInstanceExpressionCore (rc, rhs);
 
-                               // Using this check to detect probing instance expression resolve
-                               if (!rc.OmitStructFlowAnalysis) {
-                                       var fe = me as FieldExpr;
-                                       if (fe != null && fe.IsMarshalByRefAccess (rc)) {
-                                               rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
-                                               rc.Report.Warning (1690, 1, loc,
-                                                       "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
-                                                       me.GetSignatureForError ());
-                                       }
+                               var fe = me as FieldExpr;
+                               if (fe != null && fe.IsMarshalByRefAccess (rc)) {
+                                       rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
+                                       rc.Report.Warning (1690, 1, loc,
+                                               "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
+                                               me.GetSignatureForError ());
                                }
 
                                return true;
                        }
 
-                       //
-                       // Run member-access postponed check once we know that
-                       // the expression is not field expression which is the only
-                       // expression which can use uninitialized this
-                       //
-                       if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
-                               ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc);
-                       }
-
                        //
                        // Additional checks for l-value member access
                        //
@@ -3517,6 +3557,8 @@ namespace Mono.CSharp {
        /// </summary>
        public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider
        {
+               static readonly MemberSpec[] Excluded = new MemberSpec[0];
+
                protected IList<MemberSpec> Methods;
                MethodSpec best_candidate;
                TypeSpec best_candidate_return;
@@ -3566,6 +3608,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsConditionallyExcluded {
+                       get {
+                               return Methods == Excluded;
+                       }
+               }
+
                public override bool IsInstance {
                        get {
                                if (best_candidate != null)
@@ -3635,7 +3683,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (best_candidate.IsConditionallyExcluded (ec))
+                       if (IsConditionallyExcluded)
                                ec.Report.Error (765, loc,
                                        "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
                        
@@ -3760,6 +3808,10 @@ namespace Mono.CSharp {
                                ErrorIsInaccesible (ec, best_candidate.GetSignatureForError (), loc);
                        }
 
+                       // Speed up the check by not doing it on disallowed targets
+                       if (best_candidate_return.Kind == MemberKind.Void && best_candidate.IsConditionallyExcluded (ec))
+                               Methods = Excluded;
+
                        return this;
                }
 
@@ -5696,18 +5748,14 @@ namespace Mono.CSharp {
                                        // "a.b" is initialized, not whether the whole struct "a" is initialized.
 
                                        if (lvalue_instance) {
-                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
+                                               bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
 
-                                                       Expression right_side =
-                                                               out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
+                                               Expression right_side =
+                                                       out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
 
-                                                       InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
-                                               }
+                                               InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
                                        } else {
-                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
-                                               }
+                                               InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
                                        }
 
                                        if (InstanceExpression == null)
@@ -5720,10 +5768,6 @@ namespace Mono.CSharp {
                        var fb = spec as FixedFieldSpec;
                        IVariableReference var = InstanceExpression as IVariableReference;
 
-                       if (lvalue_instance && var != null && var.VariableInfo != null) {
-                               var.VariableInfo.SetStructFieldAssigned (ec, Name);
-                       }
-
                        if (fb != null) {
                                IFixedExpression fe = InstanceExpression as IFixedExpression;
                                if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
@@ -5747,15 +5791,50 @@ namespace Mono.CSharp {
                        //
                        if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
                                variable_info = var.VariableInfo.GetStructFieldInfo (Name);
-                               if (rhs != null && variable_info != null)
-                                       variable_info.SetStructFieldAssigned (ec, Name);
                        }
 
                        eclass = ExprClass.Variable;
                        return this;
                }
 
-               public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
+               public void SetFieldAssigned (FlowAnalysisContext fc)
+               {
+                       if (!IsInstance)
+                               return;
+
+                       bool lvalue_instance = spec.DeclaringType.IsStruct;
+                       if (lvalue_instance) {
+                               var var = InstanceExpression as IVariableReference;
+                               if (var != null && var.VariableInfo != null) {
+                                       fc.SetStructFieldAssigned (var.VariableInfo, Name);
+                               }
+                       }
+
+                       var fe = InstanceExpression as FieldExpr;
+                       if (fe != null || lvalue_instance) {
+                               if (fe == null)
+                                       return;
+
+                               /*
+                               while (fe.InstanceExpression is FieldExpr) {
+                                       fe = (FieldExpr) fe.InstanceExpression;
+                                       if (!fe.Spec.DeclaringType.IsStruct)
+                                               continue;
+
+                                       if (fe.VariableInfo != null && fc.IsStructFieldDefinitelyAssigned (fe.VariableInfo, fe.Name)) {
+                                               fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
+                                       }
+                               }
+
+                               fe.InstanceExpression.FlowAnalysis (fc);
+                               */
+                       } else {
+                               InstanceExpression.FlowAnalysis (fc);
+                       }
+               }
+
+
+               public void VerifyAssignedStructField (FlowAnalysisContext fc)
                {
                        var fe = this;
 
@@ -5764,14 +5843,8 @@ namespace Mono.CSharp {
                                if (var != null) {
                                        var vi = var.VariableInfo;
 
-                                       if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
-                                               if (rhs != null) {
-                                                       rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
-                                               } else {
-                                                       rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
-                                               }
-
-                                               return;
+                                       if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, fe.Name) && !fe.type.IsStruct) {
+                                               fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
                                        }
                                }
 
@@ -5809,7 +5882,6 @@ 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;
                        }
 
@@ -5875,6 +5947,23 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var var = InstanceExpression as IVariableReference;
+                       if (var != null) {
+                               var vi = var.VariableInfo;
+                               if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, Name)) {
+                                       fc.Report.Error (170, loc, "Use of possibly unassigned field `{0}'", Name);
+                                       return;
+                               }
+
+                               if (TypeSpec.IsValueType (InstanceExpression.Type))
+                                       return;
+                       }
+
+                       base.FlowAnalysis (fc);
+               }
+
                public override int GetHashCode ()
                {
                        return spec.GetHashCode ();
@@ -6742,6 +6831,11 @@ namespace Mono.CSharp {
                                DoEmit (ec);
                        }
 
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               return false;
+                       }
+
                        protected override void CloneTo (CloneContext clonectx, Statement target)
                        {
                                // Nothing
@@ -6843,10 +6937,6 @@ namespace Mono.CSharp {
                public override VariableInfo VariableInfo {
                        get { return null; }
                }
-
-               public override void VerifyDefiniteAssignment (ResolveContext rc)
-               {
-               }
        }
 
        ///