Update
[mono.git] / mcs / mcs / expression.cs
old mode 100755 (executable)
new mode 100644 (file)
index 058b97d..a6598da
@@ -217,6 +217,10 @@ namespace Mono.CSharp {
                                e = new IntConstant (-((ShortConstant) expr).Value);
                        else if (expr is UShortConstant)
                                e = new IntConstant (-((UShortConstant) expr).Value);
+                       else if (expr is SByteConstant)
+                               e = new IntConstant (-((SByteConstant) expr).Value);
+                       else if (expr is ByteConstant)
+                               e = new IntConstant (-((ByteConstant) expr).Value);
                        return e;
                }
 
@@ -237,7 +241,7 @@ namespace Mono.CSharp {
                                
                        case Operator.UnaryNegation:
                                result = TryReduceNegative (e);
-                               return true;
+                               return result != null;
                                
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
@@ -427,13 +431,15 @@ namespace Mono.CSharp {
                                }
 
                                IVariable variable = Expr as IVariable;
-                               if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+                               bool is_fixed = variable != null && variable.VerifyFixed (false);
+
+                               if (!ec.InFixedInitializer && !is_fixed) {
                                        Error (212, "You can only take the address of an unfixed expression inside " +
                                               "of a fixed statement initializer");
                                        return null;
                                }
 
-                               if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+                               if (ec.InFixedInitializer && is_fixed) {
                                        Error (213, "You can not fix an already fixed expression");
                                        return null;
                                }
@@ -655,7 +661,7 @@ namespace Mono.CSharp {
        // after semantic analysis (this is so we can take the address
        // of an indirection).
        //
-       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
                Expression expr;
                LocalTemporary temporary;
                bool prepared;
@@ -729,6 +735,21 @@ namespace Mono.CSharp {
                {
                        return "*(" + expr + ")";
                }
+
+               #region IVariable Members
+
+               public VariableInfo VariableInfo {
+                       get {
+                               return null;
+                       }
+               }
+
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return true;
+               }
+
+               #endregion
        }
        
        /// <summary>
@@ -2693,8 +2714,8 @@ namespace Mono.CSharp {
                                ((oper == Operator.LogicalAnd && (bool)lc.GetValue () == false) ||
                                 (oper == Operator.LogicalOr && (bool)lc.GetValue () == true))) {
 
-                               // TODO: make a sence to resolve unreachable expression as we do for statement
-                               Report.Warning (429, 1, loc, "Unreachable expression code detected");
+                               // TODO: make a sense to resolve unreachable expression as we do for statement
+                               Report.Warning (429, 4, loc, "Unreachable expression code detected");
                                return left;
                        }
 
@@ -3409,17 +3430,26 @@ namespace Mono.CSharp {
                                //
                                left.Emit (ec);
                                ig.Emit (OpCodes.Conv_I);
-                               right.Emit (ec);
-                               if (size != 1){
-                                       if (size == 0)
-                                               ig.Emit (OpCodes.Sizeof, element);
-                                       else 
-                                               IntLiteral.EmitInt (ig, size);
-                                       if (rtype == TypeManager.int64_type)
-                                               ig.Emit (OpCodes.Conv_I8);
-                                       else if (rtype == TypeManager.uint64_type)
-                                               ig.Emit (OpCodes.Conv_U8);
-                                       ig.Emit (OpCodes.Mul);
+
+                               Constant right_const = right as Constant;
+                               if (right_const != null && size != 0) {
+                                       Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size), right_const, loc);
+                                       if (ex == null)
+                                               return;
+                                       ex.Emit (ec);
+                               } else {
+                                       right.Emit (ec);
+                                       if (size != 1){
+                                               if (size == 0)
+                                                       ig.Emit (OpCodes.Sizeof, element);
+                                               else 
+                                                       IntLiteral.EmitInt (ig, size);
+                                               if (rtype == TypeManager.int64_type)
+                                                       ig.Emit (OpCodes.Conv_I8);
+                                               else if (rtype == TypeManager.uint64_type)
+                                                       ig.Emit (OpCodes.Conv_U8);
+                                               ig.Emit (OpCodes.Mul);
+                                       }
                                }
                                
                                if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
@@ -3525,13 +3555,12 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       // Dead code optimalization
                        if (expr is BoolConstant){
                                BoolConstant bc = (BoolConstant) expr;
 
-                               if (bc.Value)
-                                       return trueExpr;
-                               else
-                                       return falseExpr;
+                               Report.Warning (429, 4, bc.Value ? falseExpr.Location : trueExpr.Location, "Unreachable expression code detected");
+                               return bc.Value ? trueExpr : falseExpr;
                        }
 
                        return this;
@@ -4212,7 +4241,14 @@ namespace Mono.CSharp {
                                                pr.AddressOf (ec, mode);
                                        }
                                } else {
-                                       ((IMemoryLocation)Expr).AddressOf (ec, mode);
+                                       if (Expr is IMemoryLocation)
+                                               ((IMemoryLocation) Expr).AddressOf (ec, mode);
+                                       else {
+                                               Report.Error (
+                                                       1510, Expr.Location,
+                                                       "An lvalue is required as an argument to out or ref");
+                                               return;
+                                       }
                                }
                        } else
                                Expr.Emit (ec);
@@ -4228,13 +4264,6 @@ namespace Mono.CSharp {
                Expression expr;
                MethodBase method = null;
                
-               static Hashtable method_parameter_cache;
-
-               static Invocation ()
-               {
-                       method_parameter_cache = new PtrHashtable ();
-               }
-                       
                //
                // arguments is an ArrayList, but we do not want to typecast,
                // as it might be null.
@@ -4255,32 +4284,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   Returns the Parameters (a ParameterData interface) for the
-               ///   Method `mb'
-               /// </summary>
-               public static ParameterData GetParameterData (MethodBase mb)
-               {
-                       object pd = method_parameter_cache [mb];
-                       object ip;
-                       
-                       if (pd != null)
-                               return (ParameterData) pd;
-
-                       
-                       ip = TypeManager.LookupParametersByBuilder (mb);
-                       if (ip != null){
-                               method_parameter_cache [mb] = ip;
-
-                               return (ParameterData) ip;
-                       } else {
-                               ReflectionParameters rp = new ReflectionParameters (mb);
-                               method_parameter_cache [mb] = rp;
-
-                               return (ParameterData) rp;
-                       }
-               }
-
                /// <summary>
                ///   Determines "better conversion" as specified in 7.4.2.3
                ///
@@ -4391,41 +4394,11 @@ namespace Mono.CSharp {
                                            MethodBase candidate, bool candidate_params,
                                            MethodBase best, bool best_params, Location loc)
                {
-                       ParameterData candidate_pd = GetParameterData (candidate);
-                       ParameterData best_pd = GetParameterData (best);
+                       ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
+                       ParameterData best_pd = TypeManager.GetParameterData (best);
                
-                       int cand_count = candidate_pd.Count;
-                       
-                       //
-                       // If there is no best method, than this one
-                       // is better, however, if we already found a
-                       // best method, we cant tell. This happens
-                       // if we have:
-                       // 
-                       //      interface IFoo {
-                       //              void DoIt ();
-                       //      }
-                       //      
-                       //      interface IBar {
-                       //              void DoIt ();
-                       //      }
-                       //      
-                       //      interface IFooBar : IFoo, IBar {}
-                       //
-                       // We cant tell if IFoo.DoIt is better than IBar.DoIt
-                       //
-                       // However, we have to consider that
-                       // Trim (); is better than Trim (params char[] chars);
-                        //
-                       if (cand_count == 0 && argument_count == 0)
-                               return !candidate_params && best_params;
-
-                       if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
-                           (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
-                               if (cand_count != argument_count)
-                                       return false;
-
                        bool better_at_least_one = false;
+                       bool same = true;
                        for (int j = 0; j < argument_count; ++j) {
                                Argument a = (Argument) args [j];
 
@@ -4440,6 +4413,10 @@ namespace Mono.CSharp {
                                        if (best_params)
                                                bt = TypeManager.GetElementType (bt);
 
+                               if (ct == bt)
+                                       continue;
+
+                               same = false;
                                Type better = BetterConversion (ec, a, ct, bt, loc);
 
                                // for each argument, the conversion to 'ct' should be no worse than 
@@ -4453,17 +4430,39 @@ namespace Mono.CSharp {
                                        better_at_least_one = true;
                        }
 
-                        //
-                        // If a method (in the normal form) with the
-                        // same signature as the expanded form of the
-                        // current best params method already exists,
-                        // the expanded form is not applicable so we
-                        // force it to select the candidate
-                        //
-                        if (!candidate_params && best_params && cand_count == argument_count)
-                                return true;
+                       if (better_at_least_one)
+                               return true;
 
-                       return better_at_least_one;
+                       //
+                       // Note that this is not just an optimization.  This handles the case
+                       //
+                       //   Add (float f1, float f2, float f3);
+                       //   Add (params decimal [] foo);
+                       //
+                       // The call Add (3, 4, 5) should be ambiguous.  Without this check, the
+                       // first candidate would've chosen as better.
+                       //
+                       if (!same)
+                               return false;
+
+                       if (candidate_params == best_params) {
+                               //
+                               // We need to handle the case of a virtual function and its override.
+                               // The override is ignored during 'applicable_type' calculation.  However,
+                               // it should be chosen over the base virtual function, especially when handling
+                               // value types.
+                               //
+                               return IsAncestralType (best.DeclaringType, candidate.DeclaringType);
+                       }
+
+                       //
+                       // This handles the following cases:
+                       //
+                       //   Trim () is better than Trim (params char[] chars)
+                       //   Concat (string s1, string s2, string s3) is better than
+                       //     Concat (string s1, params string [] srest)
+                       //
+                        return !candidate_params && best_params;
                }
 
                public static string FullMethodDesc (MethodBase mb)
@@ -4482,7 +4481,7 @@ namespace Mono.CSharp {
                        sb.Append (".");
                        sb.Append (mb.Name);
                        
-                       ParameterData pd = GetParameterData (mb);
+                       ParameterData pd = TypeManager.GetParameterData (mb);
 
                        int count = pd.Count;
                        sb.Append (" (");
@@ -4572,7 +4571,7 @@ namespace Mono.CSharp {
                                                      int arg_count, MethodBase candidate,
                                                      bool do_varargs)
                {
-                       ParameterData pd = GetParameterData (candidate);
+                       ParameterData pd = TypeManager.GetParameterData (candidate);
 
                        int pd_count = pd.Count;
                        if (pd_count == 0)
@@ -4665,7 +4664,7 @@ namespace Mono.CSharp {
                static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count,
                                          MethodBase candidate)
                {
-                       ParameterData pd = GetParameterData (candidate);
+                       ParameterData pd = TypeManager.GetParameterData (candidate);
 
                        if (arg_count != pd.Count)
                                return false;
@@ -4797,6 +4796,15 @@ namespace Mono.CSharp {
 
                                candidates.Add (methods [i]);
 
+                               //
+                               // Methods marked 'override' don't take part in 'applicable_type'
+                               // computation.
+                               //
+                               if (!me.IsBase &&
+                                   methods [i].IsVirtual &&
+                                   (methods [i].Attributes & MethodAttributes.NewSlot) == 0)
+                                       continue;
+
                                if (applicable_type == null)
                                        applicable_type = decl_type;
                                else if (applicable_type != decl_type) {
@@ -4808,14 +4816,14 @@ namespace Mono.CSharp {
 
                        int candidate_top = candidates.Count;
 
-                       if (candidate_top == 0) {
+                       if (applicable_type == null) {
                                //
                                // Okay so we have failed to find anything so we
                                // return by providing info about the closest match
                                //
                                for (int i = 0; i < methods.Length; ++i) {
                                        MethodBase c = (MethodBase) methods [i];
-                                       ParameterData pd = GetParameterData (c);
+                                       ParameterData pd = TypeManager.GetParameterData (c);
 
                                        if (pd.Count != arg_count)
                                                continue;
@@ -4860,11 +4868,12 @@ namespace Mono.CSharp {
                                        int j = finalized; // where to put the next finalized candidate
                                        int k = finalized; // where to put the next undiscarded candidate
                                        for (int i = finalized; i < candidate_top; ++i) {
-                                               Type decl_type = ((MethodBase) candidates[i]).DeclaringType;
+                                               MethodBase candidate = (MethodBase) candidates [i];
+                                               Type decl_type = candidate.DeclaringType;
 
                                                if (decl_type == applicable_type) {
-                                                       candidates[k++] = candidates[j];
-                                                       candidates[j++] = candidates[i];
+                                                       candidates [k++] = candidates [j];
+                                                       candidates [j++] = candidates [i];
                                                        continue;
                                                }
 
@@ -4875,7 +4884,18 @@ namespace Mono.CSharp {
                                                    IsAncestralType (decl_type, next_applicable_type))
                                                        continue;
 
-                                               candidates[k++] = candidates[i];
+                                               candidates [k++] = candidates [i];
+
+#if false
+                                               //
+                                               // Methods marked 'override' don't take part in 'applicable_type'
+                                               // computation.
+                                               //
+                                               if (!me.IsBase &&
+                                                   candidate.IsVirtual &&
+                                                   (candidate.Attributes & MethodAttributes.NewSlot) == 0)
+                                                       continue;
+#endif
 
                                                if (next_applicable_type == null ||
                                                    IsAncestralType (next_applicable_type, decl_type))
@@ -4892,10 +4912,14 @@ namespace Mono.CSharp {
                         // Now we actually find the best method
                         //
 
-                       method = (MethodBase) candidates[0];
+                       method = (MethodBase) candidates [0];
                        method_params = candidate_to_form != null && candidate_to_form.Contains (method);
                        for (int ix = 1; ix < candidate_top; ix++){
                                MethodBase candidate = (MethodBase) candidates [ix];
+
+                               if (candidate == method)
+                                       continue;
+
                                bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
                                 
                                if (BetterFunction (ec, Arguments, arg_count, 
@@ -4983,7 +5007,7 @@ namespace Mono.CSharp {
                                                          Type delegate_type, bool may_fail,
                                                          Location loc)
                {
-                       ParameterData pd = GetParameterData (method);
+                       ParameterData pd = TypeManager.GetParameterData (method);
                        int pd_count = pd.Count;
 
                        for (int j = 0; j < arg_count; j++) {
@@ -5223,7 +5247,7 @@ namespace Mono.CSharp {
                {
                        ParameterData pd;
                        if (mb != null)
-                               pd = GetParameterData (mb);
+                               pd = TypeManager.GetParameterData (mb);
                        else
                                pd = null;
                        
@@ -5293,7 +5317,7 @@ namespace Mono.CSharp {
                static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
                                               ArrayList arguments)
                {
-                       ParameterData pd = GetParameterData (mb);
+                       ParameterData pd = TypeManager.GetParameterData (mb);
 
                        if (arguments == null)
                                return new Type [0];
@@ -5774,11 +5798,16 @@ namespace Mono.CSharp {
                                }
 
                                method = Invocation.OverloadResolve (
-                                       ec, (MethodGroupExpr) ml, Arguments, false, loc);
+                                       ec, (MethodGroupExpr) ml, Arguments, true, loc);
                                
                        }
 
-                       if (method == null) { 
+                       if (method == null) {
+                               if (almostMatchedMembers.Count != 0) {
+                                       MemberLookupFailed (ec, type, type, ".ctor", null, loc);
+                                       return null;
+                               }
+
                                 if (!is_struct || Arguments.Count > 0) {
                                        Error (1501, String.Format (
                                            "New invocation: Can not find a constructor in `{0}' for this argument list",
@@ -7051,7 +7080,7 @@ namespace Mono.CSharp {
                        if (sn == null || left == null || left.Type.Name != sn.Name)
                                return false;
 
-                       return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
+                       return ec.DeclSpace.LookupType (sn.Name, true, loc) != null;
                }
                
                // TODO: possible optimalization
@@ -7094,7 +7123,15 @@ namespace Mono.CSharp {
 
                                                object real_value = ((Constant) c.Expr).GetValue ();
 
-                                               return Constantify (real_value, t);
+                                               Expression exp = Constantify (real_value, t);
+
+                                               if (left_is_explicit && !left_is_type && !IdenticalNameAndTypeName (ec, left_original, left, loc)) {
+                                                       Report.SymbolRelatedToPreviousError (c);
+                                                       error176 (loc, c.GetSignatureForError ());
+                                                       return null;
+                                               }
+                                       
+                                               return exp;
                                        }
                                }
 
@@ -7270,12 +7307,12 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       if (expr is SimpleName){
-                               SimpleName child_expr = (SimpleName) expr;
-
-                               Expression new_expr = new SimpleName (child_expr.Name, Identifier, loc);
-
-                               return new_expr.Resolve (ec, flags);
+                       if (expr is Namespace) {
+                               Namespace ns = (Namespace) expr;
+                               FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc);
+                               if (retval == null)
+                                       Report.Error (234, loc, "The type or namespace name `{0}' could not be found in namespace `{1}'", Identifier, ns.FullName);
+                               return retval;
                        }
                                        
                        //
@@ -7339,7 +7376,8 @@ namespace Mono.CSharp {
                                return null;
 
                        if (member_lookup is TypeExpr) {
-                               if (!(expr is TypeExpr) && !(expr is SimpleName)) {
+                               if (!(expr is TypeExpr) && 
+                                   !IdenticalNameAndTypeName (ec, original, expr, loc)) {
                                        Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
                                               member_lookup.Type + "' instead");
                                        return null;
@@ -7365,47 +7403,32 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       return DoResolve (ec, null, ResolveFlags.VariableOrValue |
-                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+                       return DoResolve (ec, null, ResolveFlags.VariableOrValue | ResolveFlags.Type);
                }
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
-                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+                       return DoResolve (ec, right_side, ResolveFlags.VariableOrValue | ResolveFlags.Type);
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
                {
-                       string fname = null;
-                       MemberAccess full_expr = this;
-                       while (full_expr != null) {
-                               if (fname != null)
-                                       fname = String.Concat (full_expr.Identifier, ".", fname);
-                               else
-                                       fname = full_expr.Identifier;
-
-                               if (full_expr.Expr is SimpleName) {
-                                       string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
-                                       Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
-                                       if (fully_qualified != null)
-                                               return new TypeExpression (fully_qualified, loc);
-                               }
-
-                               full_expr = full_expr.Expr as MemberAccess;
-                       }
+                       return ResolveNamespaceOrType (ec, false);
+               }
 
-                       Expression new_expr = expr.ResolveAsTypeStep (ec);
+               public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
+               {
+                       FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec);
 
                        if (new_expr == null)
                                return null;
 
-                       if (new_expr is SimpleName){
-                               SimpleName child_expr = (SimpleName) new_expr;
-                               
-                               new_expr = new SimpleName (child_expr.Name, Identifier, loc);
-
-                               return new_expr.ResolveAsTypeStep (ec);
+                       if (new_expr is Namespace) {
+                               Namespace ns = (Namespace) new_expr;
+                               FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc);
+                               if (!silent && retval == null)
+                                       Report.Error (234, loc, "The type or namespace name `{0}' could not be found in namespace `{1}'", Identifier, ns.FullName);
+                               return retval;
                        }
 
                        Type expr_type = new_expr.Type;
@@ -7416,17 +7439,21 @@ namespace Mono.CSharp {
                                return null;
                        }
                        
-                       Expression member_lookup;
-                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
-                       if (member_lookup == null)
+                       Expression member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
+                       if (!silent && member_lookup == null) {
+                               Report.Error (234, loc, "The type name `{0}' could not be found in type `{1}'", 
+                                             Identifier, new_expr.FullName);
                                return null;
+                       }
 
-                       if (member_lookup is TypeExpr){
-                               member_lookup.Resolve (ec, ResolveFlags.Type);
-                               return member_lookup;
+                       if (!(member_lookup is TypeExpr)) {
+                               Report.Error (118, loc, "'{0}.{1}' denotes a '{2}', where a type was expected",
+                                             new_expr.FullName, Identifier, member_lookup.ExprClassName ());
+                               return null;
                        } 
 
-                       return null;                    
+                       member_lookup = member_lookup.Resolve (ec, ResolveFlags.Type);
+                       return (member_lookup as TypeExpr);
                }
 
                public override void Emit (EmitContext ec)
@@ -8576,9 +8603,9 @@ namespace Mono.CSharp {
                                //
                                // For now, fall back to the full lookup in that case.
                                //
-                               type = RootContext.LookupType (
-                                       ec.DeclSpace, cname, false, loc);
-
+                               FullNamedExpression e = ec.DeclSpace.LookupType (cname, false, loc);
+                               if (e is TypeExpr)
+                                       type = ((TypeExpr) e).ResolveType (ec);
                                if (type == null)
                                        return null;
                        }
@@ -8587,6 +8614,12 @@ namespace Mono.CSharp {
                                UnsafeError (loc);
                                return null;
                        }
+
+                       if (type.IsArray && (type.GetElementType () == TypeManager.arg_iterator_type ||
+                               type.GetElementType () == TypeManager.typed_reference_type)) {
+                               Report.Error (611, loc, "Array elements cannot be of type '{0}'", TypeManager.CSharpName (type.GetElementType ()));
+                               return null;
+                       }
                        
                        eclass = ExprClass.Type;
                        return this;
@@ -8597,6 +8630,12 @@ namespace Mono.CSharp {
                                return left + dim;
                        }
                }
+
+               public override string FullName {
+                       get {
+                               return type.FullName;
+                       }
+               }
        }
 
        //