**** Merged r40457-r40460 from MCS ****
[mono.git] / mcs / gmcs / expression.cs
index 9fbf4d75702060f84f30c418a85e153984de9624..9a5c6b8170054f4fd1fa948351c8556b4bb3d4f0 100644 (file)
@@ -431,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;
                                }
@@ -661,7 +663,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;
@@ -735,6 +737,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>
@@ -3458,17 +3475,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)
@@ -4290,13 +4316,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.
@@ -4317,31 +4336,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
                ///
@@ -4457,43 +4451,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 is_equal = true;
-
+                       bool same = true;
                        for (int j = 0; j < argument_count; ++j) {
                                Argument a = (Argument) args [j];
 
@@ -4508,9 +4470,10 @@ namespace Mono.CSharp {
                                        if (best_params)
                                                bt = TypeManager.GetElementType (bt);
 
-                               if (!ct.Equals (bt))
-                                       is_equal = false;
+                               if (ct.Equals (bt))
+                                       continue;
 
+                               same = false;
                                Type better = BetterConversion (ec, a, ct, bt, loc);
                                // for each argument, the conversion to 'ct' should be no worse than 
                                // the conversion to 'bt'.
@@ -4523,28 +4486,48 @@ 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;
+
+                       if (!same)
+                               return false;
 
                        //
                        // If two methods have equal parameter types, but
                        // only one of them is generic, the non-generic one wins.
                        //
-                       if (is_equal) {
-                               if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
-                                       return true;
-                               else if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
-                                       return false;
+                       if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
+                               return true;
+                       else if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
+                               return false;
+
+                       //
+                       // 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 (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);
                        }
 
-                       return better_at_least_one;
+                       //
+                       // 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)
@@ -4563,7 +4546,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 (" (");
@@ -4657,7 +4640,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;
 
@@ -4755,7 +4738,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;
@@ -4887,6 +4870,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) {
@@ -4898,14 +4890,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;
@@ -4925,7 +4917,7 @@ namespace Mono.CSharp {
                                         
                                        for (int i = 0; i < methods.Length; ++i) {
                                                MethodBase c = methods [i];
-                                               ParameterData pd = GetParameterData (c);
+                                               ParameterData pd = TypeManager.GetParameterData (c);
 
                                                if (pd.Count != arg_count)
                                                        continue;
@@ -4971,11 +4963,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;
                                                }
 
@@ -4986,7 +4979,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))
@@ -5003,10 +5007,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, 
@@ -5093,7 +5101,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++) {
@@ -5336,7 +5344,7 @@ namespace Mono.CSharp {
                {
                        ParameterData pd;
                        if (mb != null)
-                               pd = GetParameterData (mb);
+                               pd = TypeManager.GetParameterData (mb);
                        else
                                pd = null;
                        
@@ -5406,7 +5414,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];
@@ -6887,6 +6895,9 @@ namespace Mono.CSharp {
                        if ((block != null) && (block.ThisVariable != null))
                                variable_info = block.ThisVariable.VariableInfo;
 
+                       if (ec.CurrentAnonymousMethod != null)
+                               ec.CaptureThis ();
+                       
                        return true;
                }
 
@@ -7283,7 +7294,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;
                                        }
                                }
 
@@ -7606,6 +7625,11 @@ namespace Mono.CSharp {
                }
 
                public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+               {
+                       return ResolveNamespaceOrType (ec, false);
+               }
+
+               public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
                {
                        FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec);
 
@@ -7619,7 +7643,7 @@ namespace Mono.CSharp {
                                FullNamedExpression retval = ns.Lookup (ec.DeclSpace, lookup_id, loc);
                                if ((retval != null) && (args != null))
                                        retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec);
-                               if (retval == null)
+                               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;
                        }
@@ -7638,7 +7662,7 @@ namespace Mono.CSharp {
 
                        Expression member_lookup;
                        member_lookup = MemberLookupFinal (ec, expr_type, expr_type, lookup_id, loc);
-                       if (member_lookup == null) {
+                       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;