CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
}
- static readonly string[] attribute_targets = new string[] { "param" };
+ static readonly string[] attribute_targets = new [] { "param" };
FullNamedExpression texpr;
Modifier modFlags;
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>
{
var pa = rc.Module.PredefinedAttributes;
TypeSpec caller_type;
+ Attribute callerMemberName = null, callerFilePath = null;
foreach (var attr in attributes.Attrs) {
var atype = attr.ResolveTypeForComparison ();
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;
}
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)
} 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;
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;
}
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
} 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)) {}
//
return new TypeExpression (p_type, location);
}
+ public void SetIndex (int index)
+ {
+ idx = index;
+ }
+
public void Warning_UselessOptionalParameter (Report Report)
{
Report.Warning (1066, 1, Location,
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; }
}
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
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
//
{
}
- 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;
}