REF = 1 << 1,
OUT = 1 << 2,
This = 1 << 3,
+ CallerMemberName = 1 << 4,
+ CallerLineNumber = 1 << 5,
+ CallerFilePath = 1 << 6,
RefOutMask = REF | OUT,
ModifierMask = PARAMS | REF | OUT | This,
+ CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath
}
static readonly string[] attribute_targets = new string[] { "param" };
FullNamedExpression texpr;
- readonly Modifier modFlags;
+ Modifier modFlags;
string name;
Expression default_expr;
protected TypeSpec parameter_type;
TemporaryVariableReference expr_tree_variable;
- HoistedVariable hoisted_variant;
+ HoistedParameter hoisted_variant;
public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc)
{
if (a.Type == pa.CLSCompliant) {
a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
- }
-
- if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
+ } else if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) {
if (HasOptionalExpression) {
a.Report.Error (1745, a.Location,
"Cannot specify `{0}' attribute on optional parameter `{1}'",
if (a.Type == pa.DefaultParameterValue)
return;
+ } else if (a.Type == pa.CallerMemberNameAttribute) {
+ if ((modFlags & Modifier.CallerMemberName) == 0) {
+ a.Report.Error (4022, a.Location,
+ "The CallerMemberName attribute can only be applied to parameters with default value");
+ }
+ } else if (a.Type == pa.CallerLineNumberAttribute) {
+ if ((modFlags & Modifier.CallerLineNumber) == 0) {
+ a.Report.Error (4020, a.Location,
+ "The CallerLineNumber attribute can only be applied to parameters with default value");
+ }
+ } else if (a.Type == pa.CallerFilePathAttribute) {
+ if ((modFlags & Modifier.CallerFilePath) == 0) {
+ a.Report.Error (4021, a.Location,
+ "The CallerFilePath attribute can only be applied to parameters with default value");
+ }
}
base.ApplyAttributeBuilder (a, ctor, cdata, pa);
return parameter_type;
}
+ void ResolveCallerAttributes (ResolveContext rc)
+ {
+ var pa = rc.Module.PredefinedAttributes;
+ TypeSpec caller_type;
+
+ foreach (var attr in attributes.Attrs) {
+ var atype = attr.ResolveType ();
+ if (atype == null)
+ continue;
+
+ if (atype == pa.CallerMemberNameAttribute) {
+ caller_type = rc.BuiltinTypes.String;
+ if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
+ rc.Report.Error (4019, attr.Location,
+ "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+ caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+ }
+
+ modFlags |= Modifier.CallerMemberName;
+ continue;
+ }
+
+ if (atype == pa.CallerLineNumberAttribute) {
+ caller_type = rc.BuiltinTypes.Int;
+ if (caller_type != parameter_type && !Convert.ImplicitNumericConversionExists (caller_type, parameter_type)) {
+ rc.Report.Error (4017, attr.Location,
+ "The CallerMemberName attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+ caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+ }
+
+ modFlags |= Modifier.CallerLineNumber;
+ continue;
+ }
+
+ if (atype == pa.CallerFilePathAttribute) {
+ caller_type = rc.BuiltinTypes.String;
+ if (caller_type != parameter_type && !Convert.ImplicitReferenceConversionExists (caller_type, parameter_type)) {
+ rc.Report.Error (4018, attr.Location,
+ "The CallerFilePath attribute cannot be applied because there is no standard conversion from `{0}' to `{1}'",
+ caller_type.GetSignatureForError (), parameter_type.GetSignatureForError ());
+ }
+
+ modFlags |= Modifier.CallerFilePath;
+ continue;
+ }
+ }
+ }
+
public void ResolveDefaultValue (ResolveContext rc)
{
//
//
if (default_expr != null) {
((DefaultParameterValueExpression)default_expr).Resolve (rc, this);
+ if (attributes != null)
+ ResolveCallerAttributes (rc);
+
return;
}
return;
var pa = rc.Module.PredefinedAttributes;
-
var def_attr = attributes.Search (pa.DefaultParameterValue);
if (def_attr != null) {
if (def_attr.Resolve () == null)
//
// Hoisted parameter variant
//
- public HoistedVariable HoistedVariant {
+ public HoistedParameter HoistedVariant {
get {
return hoisted_variant;
}
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;
}