public interface IParameterData
{
+ Expression DefaultValue { get; }
bool HasExtensionMethodModifier { get; }
+ bool HasDefaultValue { get; }
Parameter.Modifier ModFlags { get; }
string Name { get; }
}
protected FullNamedExpression TypeName;
readonly Modifier modFlags;
string name;
+ Expression default_expr;
protected Type parameter_type;
public readonly Location Location;
int idx;
Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
}
- // TypeManager.default_parameter_value_attribute_type is null if !NET_2_0, or if System.dll is not referenced
+ if (HasDefaultValue && (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter)) {
+ Report.Error (1745, a.Location,
+ "Cannot specify `{0}' attribute on optional parameter `{1}'",
+ TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name);
+ return;
+ }
+
if (a.Type == pa.DefaultParameterValue) {
object val = a.GetParameterDefaultValue ();
if (val != null) {
if (!t.IsArray)
t = TypeManager.type_type;
- Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultValue attribute",
+ Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute",
TypeManager.CSharpName (t));
} else {
- Report.Error (1909, a.Location, "The DefaultValue attribute is not applicable on parameters of type `{0}'",
+ Report.Error (1909, a.Location, "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'",
TypeManager.CSharpName (parameter_type)); ;
}
return;
// <summary>
// Resolve is used in method definitions
// </summary>
- public virtual Type Resolve (IResolveContext ec)
+ public virtual Type Resolve (IResolveContext rc)
{
// HACK: to resolve attributes correctly
- this.resolve_context = ec;
+ this.resolve_context = rc;
if (parameter_type != null)
return parameter_type;
- TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false);
+ TypeExpr texpr = TypeName.ResolveAsTypeTerminal (rc, false);
if (texpr == null)
return null;
parameter_type = texpr.Type;
+ // Ignore all checks for dummy members
+ AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod;
+ if (pem != null && pem.IsDummy)
+ return parameter_type;
+
+ if (default_expr != null) {
+ EmitContext ec = new EmitContext (rc, rc.GenericDeclContainer, Location, null, parameter_type, 0);
+ default_expr = default_expr.Resolve (ec);
+ if (default_expr != null) {
+ Constant value = default_expr as Constant;
+ if (value == null) {
+ if (default_expr != null && !(default_expr is DefaultValueExpression)) {
+ Report.Error (1736, default_expr.Location, "The expression being assigned to optional parameter `{0}' must be constant",
+ Name);
+ default_expr = null;
+ }
+ } else {
+ Constant c = value.ConvertImplicitly (parameter_type);
+ if (c == null) {
+ if (parameter_type == TypeManager.object_type) {
+ Report.Error (1763, Location,
+ "Optional parameter `{0}' of type `{1}' can only be initialized with `null'",
+ Name, GetSignatureForError ());
+ } else {
+ Report.Error (1750, Location,
+ "Optional parameter value `{0}' cannot be converted to parameter type `{1}'",
+ value.GetValue (), GetSignatureForError ());
+ }
+ default_expr = null;
+ }
+ }
+ }
+ }
+
if ((modFlags & Parameter.Modifier.ISBYREF) != 0 &&
TypeManager.IsSpecialType (parameter_type)) {
Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
return null;
}
- var tp = TypeManager.LookupTypeParameter (parameter_type);
- if (tp != null) {
- if ((modFlags & Parameter.Modifier.ISBYREF) != 0) {
- if (tp.Variance != Variance.None)
- tp.ErrorInvalidVariance ((MemberCore) ec, Variance.None);
- } else if (tp.Variance == Variance.Covariant) {
- tp.ErrorInvalidVariance ((MemberCore) ec, Variance.Contravariant);
- }
- } else {
- if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
- Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
- texpr.GetSignatureForError ());
- return parameter_type;
- }
+ TypeManager.CheckTypeVariance (parameter_type,
+ (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
+ rc as MemberCore);
- if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
- Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
- TypeManager.CSharpName (parameter_type));
- }
+ if (texpr is TypeParameterExpr)
+ return parameter_type;
+
+ if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+ Report.Error (721, Location, "`{0}': static types cannot be used as parameters",
+ texpr.GetSignatureForError ());
+ return parameter_type;
+ }
+
+ if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
+ Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
+ TypeManager.CSharpName (parameter_type));
}
return parameter_type;
this.idx = idx;
}
+ public bool HasDefaultValue {
+ get { return default_expr != null; }
+ }
+
public bool HasExtensionMethodModifier {
get { return (modFlags & Modifier.This) != 0; }
}
}
ParameterAttributes Attributes {
- get { return ParametersCompiled.GetParameterAttribute (modFlags); }
+ get { return ParametersCompiled.GetParameterAttribute (modFlags) |
+ (HasDefaultValue ? ParameterAttributes.Optional : ParameterAttributes.None); }
}
public override AttributeTargets AttributeTargets {
if (OptAttributes != null)
OptAttributes.Emit ();
+
+ if (HasDefaultValue) {
+ //
+ // Emit constant values for true constants only, the other
+ // constant-like expressions will rely on default value expression
+ //
+ Constant c = default_expr as Constant;
+ if (c != null) {
+ if (default_expr.Type == TypeManager.decimal_type) {
+ builder.SetCustomAttribute (Const.CreateDecimalConstantAttribute (c));
+ } else {
+ builder.SetConstant (c.GetValue ());
+ }
+ }
+ }
}
public override string[] ValidAttributeTargets {
Expression.CreateExpressionFactoryCall ("Parameter", null, arguments, Location));
}
+ public Expression DefaultValue {
+ get { return default_expr; }
+ set { default_expr = value; }
+ }
+
public void Emit (EmitContext ec)
{
int arg_idx = idx;
return parameter_expr_tree_type;
}
+
+ public void Warning_UselessOptionalParameter ()
+ {
+ Report.Warning (1066, 1, Location,
+ "The default value specified for optional parameter `{0}' will never be used",
+ Name);
+ }
}
//
{
readonly string name;
readonly Parameter.Modifier modifiers;
+ readonly Expression default_value;
public ParameterData (string name, Parameter.Modifier modifiers)
{
this.modifiers = modifiers;
}
+ public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue)
+ : this (name, modifiers)
+ {
+ this.default_value = defaultValue;
+ }
+
#region IParameterData Members
+ public Expression DefaultValue {
+ get { return default_value; }
+ }
+
public bool HasExtensionMethodModifier {
get { return (modifiers & Parameter.Modifier.This) != 0; }
}
+ public bool HasDefaultValue {
+ get { return default_value != null; }
+ }
+
public Parameter.Modifier ModFlags {
get { return modifiers & ~Parameter.Modifier.This; }
}
ParameterInfo p = pi [i];
Parameter.Modifier mod = 0;
+ Expression default_value = null;
if (types [i].IsByRef) {
if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
mod = Parameter.Modifier.OUT;
(method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
method.IsDefined (extension_attr.Type, false)) {
mod = Parameter.Modifier.This;
- } else if (i >= pi.Length - 2 && types [i].IsArray) {
- if (p.IsDefined (param_attr.Type, false)) {
- mod = Parameter.Modifier.PARAMS;
- is_params = true;
+ } else {
+ if (i >= pi.Length - 2) {
+ if (types[i].IsArray) {
+ if (p.IsDefined (param_attr.Type, false)) {
+ mod = Parameter.Modifier.PARAMS;
+ is_params = true;
+ }
+ } else if (types[i] == TypeManager.runtime_argument_handle_type) {
+ par[i] = new ArglistParameter (Location.Null);
+ continue;
+ }
+ }
+
+ if (!is_params && p.IsOptional) {
+ if (p.DefaultValue == Missing.Value)
+ default_value = EmptyExpression.Null;
+ else
+ default_value = Constant.CreateConstant (types[i], p.DefaultValue, Location.Null);
}
}
- par [i] = new ParameterData (p.Name, mod);
+ par [i] = new ParameterData (p.Name, mod, default_value);
}
return method != null ?