[Facades] Moved subdirs list to subdirs.make
[mono.git] / mcs / mcs / parameter.cs
index b9e9a2a97a662dbfa6977765b6cc8284663d6a39..275f1013e8b9dfb533215ddeaeb466e4d4a8faf9 100644 (file)
@@ -222,7 +222,7 @@ namespace Mono.CSharp {
                        CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
                }
 
-               static readonly string[] attribute_targets = new string[] { "param" };
+               static readonly string[] attribute_targets = new [] { "param" };
 
                FullNamedExpression texpr;
                Modifier modFlags;
@@ -235,7 +235,7 @@ namespace Mono.CSharp {
 
                TemporaryVariableReference expr_tree_variable;
 
-               HoistedVariable hoisted_variant;
+               HoistedParameter hoisted_variant;
 
                public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
                {
@@ -338,7 +338,7 @@ namespace Mono.CSharp {
                                if (HasOptionalExpression) {
                                        a.Report.Error (1745, a.Location,
                                                "Cannot specify `{0}' attribute on optional parameter `{1}'",
-                                               TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
+                                               a.Type.GetSignatureForError ().Replace ("Attribute", ""), Name);
                                }
 
                                if (a.Type == pa.DefaultParameterValue)
@@ -371,6 +371,15 @@ namespace Mono.CSharp {
                        return member.IsAccessibleAs (parameter_type);
                }
 
+               bool IsValidCallerContext (MemberCore memberContext)
+               {
+                       var m = memberContext as Method;
+                       if (m != null)
+                               return !m.IsPartialImplementation;
+
+                       return true;
+               }
+
                // <summary>
                //   Resolve is used in method definitions
                // </summary>
@@ -394,7 +403,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       TypeManager.CheckTypeVariance (parameter_type,
+                       VarianceDecl.CheckTypeVariance (parameter_type,
                                (modFlags & Parameter.Modifier.RefOutMask) != 0 ? Variance.None : Variance.Contravariant,
                                rc);
 
@@ -406,7 +415,7 @@ namespace Mono.CSharp {
 
                        if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
                                rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'",
-                                       TypeManager.CSharpName (parameter_type));
+                                       parameter_type.GetSignatureForError ());
                        }
 
                        return parameter_type;
@@ -416,9 +425,10 @@ namespace Mono.CSharp {
                {
                        var pa = rc.Module.PredefinedAttributes;
                        TypeSpec caller_type;
+                       Attribute callerMemberName = null, callerFilePath = null;
 
                        foreach (var attr in attributes.Attrs) {
-                               var atype = attr.ResolveType ();
+                               var atype = attr.ResolveTypeForComparison ();
                                if (atype == null)
                                        continue;
 
@@ -430,18 +440,31 @@ namespace Mono.CSharp {
                                                        caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
                                        }
 
+                                       if (!IsValidCallerContext (rc.CurrentMemberDefinition)) {
+                                               rc.Report.Warning (4026, 1, attr.Location,
+                                                       "The CallerMemberName applied to parameter `{0}' will have no effect because it applies to a member that is used in context that do not allow optional arguments",
+                                                       name);
+                                       }
+
                                        modFlags |= Modifier.CallerMemberName;
+                                       callerMemberName = attr;
                                        continue;
                                }
 
                                if (atype == pa.CallerLineNumberAttribute) {
                                        caller_type = rc.BuiltinTypes.Int;
-                                       if (caller_type != parameter_type && !Convert.ImplicitNumericConversionExists (caller_type, parameter_type)) {
+                                       if (caller_type != parameter_type && !Convert.ImplicitStandardConversionExists (new IntConstant (caller_type, int.MaxValue, Location.Null), parameter_type)) {
                                                rc.Report.Error (4017, attr.Location,
-                                                       "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+                                                       "The CallerLineNumberAttribute attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
                                                        caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
                                        }
 
+                                       if (!IsValidCallerContext (rc.CurrentMemberDefinition)) {
+                                               rc.Report.Warning (4024, 1, attr.Location,
+                                                       "The CallerLineNumberAttribute applied to parameter `{0}' will have no effect because it applies to a member that is used in context that do not allow optional arguments",
+                                                       name);
+                                       }
+
                                        modFlags |= Modifier.CallerLineNumber;
                                        continue;
                                }
@@ -454,10 +477,40 @@ namespace Mono.CSharp {
                                                        caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
                                        }
 
+                                       if (!IsValidCallerContext (rc.CurrentMemberDefinition)) {
+                                               rc.Report.Warning (4025, 1, attr.Location,
+                                                       "The CallerFilePath applied to parameter `{0}' will have no effect because it applies to a member that is used in context that do not allow optional arguments",
+                                                       name);
+                                       }
+
                                        modFlags |= Modifier.CallerFilePath;
+                                       callerFilePath = attr;
                                        continue;
                                }
                        }
+
+                       if ((modFlags & Modifier.CallerLineNumber) != 0) {
+                               if (callerMemberName != null) {
+                                       rc.Report.Warning (7081, 1, callerMemberName.Location,
+                                               "The CallerMemberNameAttribute applied to parameter `{0}' will have no effect. It is overridden by the CallerLineNumberAttribute",
+                                               Name);
+                               }
+
+                               if (callerFilePath != null) {
+                                       rc.Report.Warning (7082, 1, callerFilePath.Location,
+                                               "The CallerFilePathAttribute applied to parameter `{0}' will have no effect. It is overridden by the CallerLineNumberAttribute",
+                                               name);
+                               }
+                       }
+
+                       if ((modFlags & Modifier.CallerMemberName) != 0) {
+                               if (callerFilePath != null) {
+                                       rc.Report.Warning (7080, 1, callerFilePath.Location,
+                                               "The CallerMemberNameAttribute applied to parameter `{0}' will have no effect. It is overridden by the CallerFilePathAttribute",
+                                               name);
+                               }
+
+                       }
                }
 
                public void ResolveDefaultValue (ResolveContext rc)
@@ -501,7 +554,7 @@ namespace Mono.CSharp {
                                        } else {
                                                rc.Report.Error (1909, default_expr.Location,
                                                        "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
-                                                       default_expr.Type.GetSignatureForError ()); ;
+                                                       default_expr.Type.GetSignatureForError ());
                                        }
 
                                        default_expr = null;
@@ -510,7 +563,8 @@ namespace Mono.CSharp {
 
                                if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) ||
                                        (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) ||
-                                       parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
+                                       parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object ||
+                                       parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
                                        return;
                                }
 
@@ -549,7 +603,7 @@ namespace Mono.CSharp {
                //
                // Hoisted parameter variant
                //
-               public HoistedVariable HoistedVariant {
+               public HoistedParameter HoistedVariant {
                        get {
                                return hoisted_variant;
                        }
@@ -582,7 +636,7 @@ namespace Mono.CSharp {
                {
                        string type_name;
                        if (parameter_type != null)
-                               type_name = TypeManager.CSharpName (parameter_type);
+                               type_name = parameter_type.GetSignatureForError ();
                        else
                                type_name = texpr.GetSignatureForError ();
 
@@ -635,7 +689,7 @@ namespace Mono.CSharp {
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
-                       if (HasDefaultValue) {
+                       if (HasDefaultValue && default_expr.Type != null) {
                                //
                                // Emit constant values for true constants only, the other
                                // constant-like expressions will rely on default value expression
@@ -648,9 +702,9 @@ namespace Mono.CSharp {
                                        } else {
                                                builder.SetConstant (c.GetValue ());
                                        }
-                               } else if (default_expr.Type.IsStruct) {
+                               } else if (default_expr.Type.IsStruct || default_expr.Type.IsGenericParameter) {
                                        //
-                                       // Handles special case where default expression is used with value-type
+                                       // Handles special case where default expression is used with value-type or type parameter
                                        //
                                        // void Foo (S s = default (S)) {}
                                        //
@@ -724,6 +778,11 @@ namespace Mono.CSharp {
                        return new TypeExpression (p_type, location);
                }
 
+               public void SetIndex (int index)
+               {
+                       idx = index;
+               }
+
                public void Warning_UselessOptionalParameter (Report Report)
                {
                        Report.Warning (1066, 1, Location,
@@ -817,7 +876,7 @@ namespace Mono.CSharp {
 
                public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags)
                {
-                       return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
+                       return (modFlags & Parameter.Modifier.OUT) != 0 ?
                                ParameterAttributes.Out : ParameterAttributes.None;
                }
 
@@ -900,6 +959,19 @@ namespace Mono.CSharp {
                        return sb.ToString ();
                }
 
+               public static bool HasSameParameterDefaults (AParametersCollection a, AParametersCollection b)
+               {
+                       if (a == null)
+                               return b == null;
+
+                       for (int i = 0; i < a.Count; ++i) {
+                               if (a.FixedParameters [i].HasDefaultValue != b.FixedParameters [i].HasDefaultValue)
+                                       return false;
+                       }
+
+                       return true;
+               }
+
                public bool HasArglist {
                        get { return has_arglist; }
                }
@@ -932,9 +1004,14 @@ namespace Mono.CSharp {
                                        if (inflated_param == types[i])
                                                continue;
 
-                                       default_value |= FixedParameters[i] is DefaultValueExpression;
+                                       default_value |= FixedParameters[i].HasDefaultValue;
                                        inflated_types = new TypeSpec[types.Length];
-                                       Array.Copy (types, inflated_types, types.Length);       
+                                       Array.Copy (types, inflated_types, types.Length);
+                               } else {
+                                       if (inflated_param == types[i])
+                                               continue;
+
+                                       default_value |= FixedParameters[i].HasDefaultValue;
                                }
 
                                inflated_types[i] = inflated_param;
@@ -945,13 +1022,42 @@ namespace Mono.CSharp {
 
                        var clone = (AParametersCollection) MemberwiseClone ();
                        clone.types = inflated_types;
+
+                       //
+                       // Default expression is original expression from the parameter
+                       // declaration context which can be of nested enum in generic class type.
+                       // In such case we end up with expression type of G<T>.E and e.g. parameter
+                       // type of G<int>.E and conversion would fail without inflate in this
+                       // context.
+                       //
                        if (default_value) {
+                               clone.parameters = new IParameterData[Count];
                                for (int i = 0; i < Count; ++i) {
-                                       var dve = clone.FixedParameters[i] as DefaultValueExpression;
-                                       if (dve != null) {
-                                               throw new NotImplementedException ("net");
-                                               //      clone.FixedParameters [i].DefaultValue = new DefaultValueExpression ();
-                                       }
+                                       var fp = FixedParameters[i];
+                                       clone.FixedParameters[i] = fp;
+
+                                       if (!fp.HasDefaultValue)
+                                               continue;
+
+                                       var expr = fp.DefaultValue;
+
+                                       if (inflated_types[i] == expr.Type)
+                                               continue;
+
+                                       var c = expr as Constant;
+                                       if (c != null) {
+                                               //
+                                               // It may fail we are inflating before type validation is done
+                                               //
+                                               c = Constant.ExtractConstantFromValue (inflated_types[i], c.GetValue (), expr.Location);
+                                               if (c == null)
+                                                       expr = new DefaultValueExpression (new TypeExpression (inflated_types[i], expr.Location), expr.Location);
+                                               else
+                                                       expr = c;
+                                       } else if (expr is DefaultValueExpression)
+                                               expr = new DefaultValueExpression (new TypeExpression (inflated_types[i], expr.Location), expr.Location);
+
+                                       clone.FixedParameters[i] = new ParameterData (fp.Name, fp.ModFlags, expr);
                                }
                        }
 
@@ -963,11 +1069,11 @@ namespace Mono.CSharp {
                        if (types == null || types [pos] == null)
                                return ((Parameter)FixedParameters [pos]).GetSignatureForError ();
 
-                       string type = TypeManager.CSharpName (types [pos]);
+                       string type = types [pos].GetSignatureForError ();
                        if (FixedParameters [pos].HasExtensionMethodModifier)
                                return "this " + type;
 
-                       Parameter.Modifier mod = FixedParameters [pos].ModFlags;
+                       var mod = FixedParameters[pos].ModFlags & Parameter.Modifier.ModifierMask;
                        if (mod == 0)
                                return type;
 
@@ -1052,6 +1158,23 @@ namespace Mono.CSharp {
                        return new ParametersCompiled (parameters, types);
                }
 
+               public static ParametersCompiled Prefix (ParametersCompiled parameters, Parameter p, TypeSpec type)
+               {
+                       var ptypes = new TypeSpec [parameters.Count + 1];
+                       ptypes [0] = type;
+                       Array.Copy (parameters.Types, 0, ptypes, 1, parameters.Count);
+
+                       var param = new Parameter [ptypes.Length];
+                       param [0] = p;
+                       for (int i = 0; i < parameters.Count; ++i) {
+                               var pi = parameters [i];
+                               param [i + 1] = pi;
+                               pi.SetIndex (i + 1);
+                       }
+
+                       return ParametersCompiled.CreateFullyResolved (param, ptypes);
+               }
+
                //
                // TODO: This does not fit here, it should go to different version of AParametersCollection
                // as the underlying type is not Parameter and some methods will fail to cast
@@ -1213,6 +1336,9 @@ namespace Mono.CSharp {
                        for (int i = 0; i < parameters.Length; ++i) {
                                Parameter p = (Parameter) parameters [i];
 
+                               if (p.Type != null)
+                                       p.Type.CheckObsoleteness (m, p.Location);
+
                                //
                                // Try not to enter default values resolution if there are is not any default value possible
                                //
@@ -1299,23 +1425,22 @@ namespace Mono.CSharp {
                {
                }
 
-               protected override Expression DoResolve (ResolveContext rc)
-               {
-                       return base.DoResolve (rc);
-               }
-
                public void Resolve (ResolveContext rc, Parameter p)
                {
                        var expr = Resolve (rc);
-                       if (expr == null)
+                       if (expr == null) {
+                               this.expr = ErrorExpression.Instance;
                                return;
+                       }
 
                        expr = Child;
 
-                       if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
-                               rc.Report.Error (1736, Location,
-                                       "The expression being assigned to optional parameter `{0}' must be a constant or default value",
-                                       p.Name);
+                       if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsGeneratedStructConstructor))) {
+                               if (!(expr is ErrorExpression)) {
+                                       rc.Report.Error (1736, Location,
+                                               "The expression being assigned to optional parameter `{0}' must be a constant or default value",
+                                               p.Name);
+                               }
 
                                return;
                        }
@@ -1352,6 +1477,8 @@ namespace Mono.CSharp {
                        rc.Report.Error (1750, Location,
                                "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'",
                                type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+
+                       this.expr = ErrorExpression.Instance;
                }
                
                public override object Accept (StructuralVisitor visitor)