{
}
- public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
{
#if !NET_2_0
- if (a.Type == TypeManager.marshal_as_attr_type) {
+ if (a.Type == pa.MarshalAs) {
UnmanagedMarshal marshal = a.GetMarshal (this);
if (marshal != null) {
builder.SetMarshal (marshal);
}
}
- public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
{
- if (a.Type == TypeManager.cls_compliant_attribute_type) {
+ if (a.Type == pa.CLSCompliant) {
Report.Warning (3023, 1, a.Location, "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead");
}
if (builder == null)
return;
- base.ApplyAttributeBuilder (a, cb);
+ base.ApplyAttributeBuilder (a, cb, pa);
}
public override AttributeTargets AttributeTargets {
public ImplicitParameter (MethodBuilder mb):
base (null)
{
- builder = mb.DefineParameter (1, ParameterAttributes.None, "");
+ builder = mb.DefineParameter (1, ParameterAttributes.None, "value");
}
public override AttributeTargets AttributeTargets {
public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
{
base.ApplyAttributes (mb, cb, index);
-
- CustomAttributeBuilder ca = TypeManager.param_array_attr;
- if (ca == null) {
- ConstructorInfo ci = TypeManager.GetPredefinedConstructor (TypeManager.param_array_type, Location, Type.EmptyTypes);
- if (ci == null)
- return;
-
- ca = new CustomAttributeBuilder (ci, new object [0]);
- if (ca == null)
- return;
-
- TypeManager.param_array_attr = ca;
- }
-
- builder.SetCustomAttribute (ca);
+ PredefinedAttributes.Get.ParamArray.EmitAttribute (builder, Location);
}
}
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;
TypeName = type;
}
- public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
{
- if (a.Type == TypeManager.in_attribute_type && ModFlags == Modifier.OUT) {
+ if (a.Type == pa.In && ModFlags == Modifier.OUT) {
Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
return;
}
- if (a.Type == TypeManager.param_array_type) {
+ if (a.Type == pa.ParamArray) {
Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead");
return;
}
- if (a.Type == TypeManager.out_attribute_type && (ModFlags & Modifier.REF) == Modifier.REF &&
- TypeManager.in_attribute_type != null && !OptAttributes.Contains (TypeManager.in_attribute_type)) {
+ if (a.Type == PredefinedAttributes.Get.Out && (ModFlags & Modifier.REF) == Modifier.REF &&
+ !OptAttributes.Contains (pa.In)) {
Report.Error (662, a.Location,
"Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
return;
}
- if (a.Type == TypeManager.cls_compliant_attribute_type) {
+ if (a.Type == pa.CLSCompliant) {
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 (a.Type == TypeManager.default_parameter_value_attribute_type) {
+ 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) {
Type t = val.GetType ();
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;
return;
}
- base.ApplyAttributeBuilder (a, cb);
+ base.ApplyAttributeBuilder (a, cb, pa);
}
public virtual bool CheckAccessibility (InterfaceMemberBase member)
// <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;
}
-#if GMCS_SOURCE
- if (parameter_type.IsGenericParameter) {
- AbstractPropertyEventMethod accessor = ec as AbstractPropertyEventMethod;
- if (accessor == null || !accessor.IsDummy) {
- if ((parameter_type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0) {
- Report.Error (-38, Location, "Covariant type parameters cannot be used as method parameters");
- return null;
- } else if ((ModFlags & Modifier.ISBYREF) != 0 &&
- (parameter_type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) {
- Report.Error (-37, Location, "Contravariant type parameters cannot be used in output positions");
- return null;
- }
- }
- return parameter_type;
- }
+ TypeManager.CheckTypeVariance (parameter_type,
+ (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant,
+ rc as MemberCore);
- if (!TypeManager.VerifyNoVariantTypeParameters (parameter_type, Location)) {
- return null;
- }
-#endif
+ 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",
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 {
public ExpressionStatement CreateExpressionTreeVariable (EmitContext ec)
{
+ //
+ // A parameter is not hoisted when used directly as ET
+ //
+ HoistedVariableReference = null;
+
if ((modFlags & Modifier.ISBYREF) != 0)
Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier");
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;
bool is_ref = (ModFlags & Modifier.ISBYREF) != 0;
if (is_ref) {
- if (arg_idx <= 255)
- ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
- else
- ec.ig.Emit (OpCodes.Ldarg, arg_idx);
+ ParameterReference.EmitLdArg (ec.ig, arg_idx);
} else {
if (arg_idx <= 255)
ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_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; }
}
Type [] types = new Type [pi.Length];
IParameterData [] par = new IParameterData [pi.Length];
bool is_params = false;
+ PredefinedAttribute extension_attr = PredefinedAttributes.Get.Extension;
+ PredefinedAttribute param_attr = PredefinedAttributes.Get.ParamArray;
for (int i = 0; i < types.Length; i++) {
types [i] = TypeManager.TypeToCoreType (pi [i].ParameterType);
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;
// Strip reference wrapping
//
types [i] = TypeManager.GetElementType (types [i]);
- } else if (i == 0 && TypeManager.extension_attribute_type != null && method != null && method.IsStatic &&
+ } else if (i == 0 && extension_attr.IsDefined && method != null && method.IsStatic &&
(method.DeclaringType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute &&
- method.IsDefined (TypeManager.extension_attribute_type, false)) {
+ method.IsDefined (extension_attr.Type, false)) {
mod = Parameter.Modifier.This;
- } else if (i >= pi.Length - 2 && types [i].IsArray) {
- if (p.IsDefined (TypeManager.param_array_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 ?