// TODO: silent flag is ignored
ct.CheckConstraints (ec);
- ct.VerifyVariantTypeParameters ();
}
return te;
/// Currently ResolveLValue wraps DoResolveLValue to perform sanity
/// checking and assertion checking on what we expect from Resolve
/// </remarks>
- public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
+ public Expression ResolveLValue (EmitContext ec, Expression right_side)
{
int errors = Report.Errors;
bool out_access = right_side == EmptyExpression.OutAccess;
if (operator_group == null)
return null;
- ArrayList arguments = new ArrayList (1);
- arguments.Add (new Argument (e, Argument.AType.Expression));
+ Arguments arguments = new Arguments (1);
+ arguments.Add (new Argument (e));
operator_group = operator_group.OverloadResolve (
ec, ref arguments, false, loc);
//
public abstract Expression CreateExpressionTree (EmitContext ec);
- protected Expression CreateExpressionFactoryCall (string name, ArrayList args)
+ protected Expression CreateExpressionFactoryCall (string name, Arguments args)
{
return CreateExpressionFactoryCall (name, null, args, loc);
}
- protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args)
+ protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, Arguments args)
{
return CreateExpressionFactoryCall (name, typeArguments, args, loc);
}
- public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args, Location loc)
+ public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, Arguments args, Location loc)
{
return new Invocation (new MemberAccess (CreateExpressionTypeExpression (loc), name, typeArguments, loc), args);
}
public override Expression CreateExpressionTree (EmitContext ec)
{
- ArrayList args = new ArrayList (2);
+ Arguments args = new Arguments (2);
args.Add (new Argument (child.CreateExpressionTree (ec)));
args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
public override Expression CreateExpressionTree (EmitContext ec)
{
- ArrayList args = new ArrayList (2);
- args.Add (new Argument (child.CreateExpressionTree (ec)));
- args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+ Arguments args = Arguments.CreateForExpressionTree (ec, null,
+ child.CreateExpressionTree (ec),
+ new TypeOf (new TypeExpression (type, loc), loc));
+
if (type.IsPointer)
Error_PointerInsideExpressionTree ();
public override void Emit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
base.Emit (ec);
-#if GMCS_SOURCE
- if (type.IsGenericParameter || type.IsGenericType && type.IsValueType)
- ig.Emit (OpCodes.Unbox_Any, type);
- else
-#endif
- {
- ig.Emit (OpCodes.Unbox, type);
- LoadFromPtr (ig, type);
- }
+ ILGenerator ig = ec.ig;
+
+#if GMCS_SOURCE
+ ig.Emit (OpCodes.Unbox_Any, type);
+#else
+ ig.Emit (OpCodes.Unbox, type);
+ LoadFromPtr (ig, type);
+#endif
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
if (vi != null){
LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
if (right_side != null) {
- return var.ResolveLValue (ec, right_side, loc);
+ return var.ResolveLValue (ec, right_side);
} else {
ResolveFlags rf = ResolveFlags.VariableOrValue;
if (intermediate)
Expression expr = current_block.Toplevel.GetParameterReference (Name, loc);
if (expr != null) {
if (right_side != null)
- return expr.ResolveLValue (ec, right_side, loc);
+ return expr.ResolveLValue (ec, right_side);
return expr.Resolve (ec);
}
get { return namespace_entry == null; }
}
- public override void EmitArguments (EmitContext ec, ArrayList arguments)
- {
- if (arguments == null)
- arguments = new ArrayList (1);
- arguments.Insert (0, extension_argument);
- base.EmitArguments (ec, arguments);
- }
-
- public override void EmitCall (EmitContext ec, ArrayList arguments)
- {
- if (arguments == null)
- arguments = new ArrayList (1);
- arguments.Insert (0, extension_argument);
- base.EmitCall (ec, arguments);
- }
-
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
extension_argument.Expr.MutateHoistedGenericType (storey);
base.MutateHoistedGenericType (storey);
}
- public override MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList arguments, bool may_fail, Location loc)
+ public override MethodGroupExpr OverloadResolve (EmitContext ec, ref Arguments arguments, bool may_fail, Location loc)
{
if (arguments == null)
- arguments = new ArrayList (1);
+ arguments = new Arguments (1);
arguments.Insert (0, new Argument (ExtensionExpression));
- MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespace_entry, loc);
+ MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc);
// Store resolved argument and restore original arguments
if (mg != null)
- ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0];
- arguments.RemoveAt (0);
+ ((ExtensionMethodGroupExpr)mg).extension_argument = arguments [0];
+ else
+ arguments.RemoveAt (0); // Clean-up modified arguments for error reporting
return mg;
}
- MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
+ MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc)
{
// Use normal resolve rules
MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
e.ExtensionExpression = ExtensionExpression;
e.SetTypeArguments (type_arguments);
- return e.ResolveOverloadExtensions (ec, arguments, e.namespace_entry, loc);
+ return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc);
}
}
public override Type DeclaringType {
get {
- //
- // We assume that the top-level type is in the end
- //
- return Methods [Methods.Length - 1].DeclaringType;
- //return Methods [0].DeclaringType;
+ return queried_type;
}
}
/// false if candidate ain't better
/// true if candidate is better than the current best match
/// </remarks>
- static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
+ static bool BetterFunction (EmitContext ec, Arguments args, int argument_count,
MethodBase candidate, bool candidate_params,
MethodBase best, bool best_params)
{
bool same = true;
for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx)
{
- Argument a = (Argument) args [j];
+ Argument a = args [j];
+
+ // Provided default argument value is never better
+ if (a.IsDefaultArgument && candidate_params == best_params)
+ return false;
Type ct = candidate_pd.Types [c_idx];
Type bt = best_pd.Types [b_idx];
if (candidate_param_count != best_param_count)
// can only happen if (candidate_params && best_params)
- return candidate_param_count > best_param_count;
+ return candidate_param_count > best_param_count && best_pd.HasParams;
//
// now, both methods have the same number of parameters, and the parameters have the same types
ReportUsageError ();
}
- public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
- {
- Invocation.EmitArguments (ec, arguments, false, null);
- }
-
- public virtual void EmitCall (EmitContext ec, ArrayList arguments)
+ public void EmitCall (EmitContext ec, Arguments arguments)
{
Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);
}
/// 0 = the best, int.MaxValue = the worst
///
public int IsApplicable (EmitContext ec,
- ArrayList arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form)
+ ref Arguments arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form)
{
MethodBase candidate = method;
AParametersCollection pd = TypeManager.GetParameterData (candidate);
int param_count = GetApplicableParametersCount (candidate, pd);
+ int optional_count = 0;
if (arg_count != param_count) {
- if (!pd.HasParams)
- return int.MaxValue - 10000 + Math.Abs (arg_count - param_count);
- if (arg_count < param_count - 1)
- return int.MaxValue - 10000 + Math.Abs (arg_count - param_count);
-
+ for (int i = 0; i < pd.Count; ++i) {
+ if (pd.FixedParameters [i].HasDefaultValue) {
+ optional_count = pd.Count - i;
+ break;
+ }
+ }
+
+ int args_gap = Math.Abs (arg_count - param_count);
+ if (optional_count != 0) {
+ if (args_gap > optional_count)
+ return int.MaxValue - 10000 + args_gap - optional_count;
+
+ // Readjust expected number when params used
+ if (pd.HasParams) {
+ optional_count--;
+ if (arg_count < param_count)
+ param_count--;
+ }
+ } else if (arg_count != param_count) {
+ if (!pd.HasParams)
+ return int.MaxValue - 10000 + args_gap;
+ if (arg_count < param_count - 1)
+ return int.MaxValue - 10000 + args_gap;
+ }
+
// Initialize expanded form of a method with 1 params parameter
params_expanded_form = param_count == 1 && pd.HasParams;
+
+ // Resize to fit optional arguments
+ if (optional_count != 0) {
+ Arguments resized;
+ if (arguments == null) {
+ resized = new Arguments (optional_count);
+ } else {
+ resized = new Arguments (param_count);
+ resized.AddRange (arguments);
+ }
+
+ for (int i = arg_count; i < param_count; ++i)
+ resized.Add (null);
+ arguments = resized;
+ }
+ }
+
+ if (arg_count > 0) {
+ //
+ // Shuffle named arguments to the right positions if there are any
+ //
+ if (arguments [arg_count - 1] is NamedArgument) {
+ arg_count = arguments.Count;
+
+ for (int i = 0; i < arg_count; ++i) {
+ bool arg_moved = false;
+ while (true) {
+ NamedArgument na = arguments[i] as NamedArgument;
+ if (na == null)
+ break;
+
+ int index = pd.GetParameterIndexByName (na.Name.Value);
+
+ // Named parameter not found or already reordered
+ if (index <= i)
+ break;
+
+ // When using parameters which should not be available to the user
+ if (index >= param_count)
+ break;
+
+ if (!arg_moved) {
+ arguments.MarkReorderedArgument (na);
+ arg_moved = true;
+ }
+
+ Argument temp = arguments[index];
+ arguments[index] = arguments[i];
+ arguments[i] = temp;
+
+ if (temp == null)
+ break;
+ }
+ }
+ } else {
+ arg_count = arguments.Count;
+ }
+ } else if (arguments != null) {
+ arg_count = arguments.Count;
}
#if GMCS_SOURCE
if (type_arguments != null)
return int.MaxValue - 15000;
}
-#endif
+#endif
//
// 2. Each argument has to be implicitly convertible to method parameter
Parameter.Modifier p_mod = 0;
Type pt = null;
for (int i = 0; i < arg_count; i++) {
- Argument a = (Argument) arguments [i];
- Parameter.Modifier a_mod = a.Modifier &
- ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
-
- if (p_mod != Parameter.Modifier.PARAMS) {
- p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+ Argument a = arguments [i];
+ if (a == null) {
+ if (!pd.FixedParameters [i].HasDefaultValue)
+ throw new InternalErrorException ();
- if (p_mod == Parameter.Modifier.ARGLIST) {
- if (a.Type == TypeManager.runtime_argument_handle_type)
- continue;
+ Expression e = pd.FixedParameters [i].DefaultValue as Constant;
+ if (e == null)
+ e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec);
- p_mod = 0;
- }
+ arguments [i] = new Argument (e, Argument.AType.Default);
+ continue;
+ }
+ if (p_mod != Parameter.Modifier.PARAMS) {
+ p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
pt = pd.Types [i];
} else {
params_expanded_form = true;
}
+ Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
int score = 1;
if (!params_expanded_form)
score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
}
if (arg_count != param_count)
- params_expanded_form = true;
+ params_expanded_form = true;
return 0;
}
/// that is the best match of me on Arguments.
///
/// </summary>
- public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList Arguments,
+ public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref Arguments Arguments,
bool may_fail, Location loc)
{
bool method_params = false;
Type applicable_type = null;
- int arg_count = 0;
ArrayList candidates = new ArrayList (2);
ArrayList candidate_overrides = null;
// false is normal form, true is expanded form
//
Hashtable candidate_to_form = null;
+ Hashtable candidates_expanded = null;
+ Arguments candidate_args = Arguments;
- if (Arguments != null)
- arg_count = Arguments.Count;
+ int arg_count = Arguments != null ? Arguments.Count : 0;
if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
if (!may_fail)
// Check if candidate is applicable (section 14.4.2.1)
//
bool params_expanded_form = false;
- int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i], ref params_expanded_form);
+ int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form);
if (candidate_rate < best_candidate_rate) {
best_candidate_rate = candidate_rate;
MethodBase candidate = Methods [i];
candidate_to_form [candidate] = candidate;
}
+
+ if (candidate_args != Arguments) {
+ if (candidates_expanded == null)
+ candidates_expanded = new Hashtable (2);
+
+ candidates_expanded.Add (Methods [i], candidate_args);
+ candidate_args = Arguments;
+ }
if (candidate_rate != 0 || has_inaccessible_candidates_only) {
if (msg_recorder != null)
// return error info about the closest match
//
if (best_candidate != null) {
- if (CustomErrorHandler != null && CustomErrorHandler.NoExactMatch (ec, best_candidate))
+ if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
return null;
AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
best_candidate = (MethodBase) candidates [0];
method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+ //
+ // TODO: Broken inverse order of candidates logic does not work with optional
+ // parameters used for method overrides and I am not going to fix it for SRE
+ //
+ if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
+ candidate_args = (Arguments) candidates_expanded [best_candidate];
+ arg_count = candidate_args.Count;
+ }
+
for (int ix = 1; ix < candidate_top; ix++) {
MethodBase candidate = (MethodBase) candidates [ix];
bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
- if (BetterFunction (ec, Arguments, arg_count,
+ if (BetterFunction (ec, candidate_args, arg_count,
candidate, cand_params,
best_candidate, method_params)) {
best_candidate = candidate;
continue;
bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
- if (!BetterFunction (ec, Arguments, arg_count,
+ if (!BetterFunction (ec, candidate_args, arg_count,
best_candidate, method_params,
candidate, cand_params))
{
// necessary etc. and return if everything is
// all right
//
- if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate,
+ if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
method_params, may_fail, loc))
return null;
return null;
MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
-#if GMCS_SOURCE
- if (the_method.IsGenericMethodDefinition &&
+ if (TypeManager.IsGenericMethodDefinition (the_method) &&
!ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
return null;
-#endif
//
// Check ObsoleteAttribute on the best method
if (data != null)
data.SetMemberIsUsed ();
+ Arguments = candidate_args;
return this;
}
type_arguments = ta;
}
- public bool VerifyArgumentsCompat (EmitContext ec, ref ArrayList arguments,
+ public bool VerifyArgumentsCompat (EmitContext ec, ref Arguments arguments,
int arg_count, MethodBase method,
bool chose_params_expanded,
bool may_fail, Location loc)
{
AParametersCollection pd = TypeManager.GetParameterData (method);
+ int param_count = GetApplicableParametersCount (method, pd);
int errors = Report.Errors;
Parameter.Modifier p_mod = 0;
bool has_unsafe_arg = false;
for (; a_idx < arg_count; a_idx++, ++a_pos) {
- a = (Argument) arguments [a_idx];
+ a = arguments [a_idx];
if (p_mod != Parameter.Modifier.PARAMS) {
p_mod = pd.FixedParameters [a_idx].ModFlags;
pt = pd.Types [a_idx];
has_unsafe_arg |= pt.IsPointer;
- if (p_mod == Parameter.Modifier.ARGLIST) {
- if (a.Type != TypeManager.runtime_argument_handle_type)
- break;
- continue;
- }
-
if (p_mod == Parameter.Modifier.PARAMS) {
if (chose_params_expanded) {
params_initializers = new ArrayList (arg_count - a_idx);
break;
continue;
+ } else {
+ NamedArgument na = a as NamedArgument;
+ if (na != null) {
+ int name_index = pd.GetParameterIndexByName (na.Name.Value);
+ if (name_index < 0 || name_index >= param_count) {
+ if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
+ Report.SymbolRelatedToPreviousError (DeclaringType);
+ Report.Error (1746, na.Name.Location,
+ "The delegate `{0}' does not contain a parameter named `{1}'",
+ TypeManager.CSharpName (DeclaringType), na.Name.Value);
+ } else {
+ Report.SymbolRelatedToPreviousError (best_candidate);
+ Report.Error (1739, na.Name.Location,
+ "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
+ TypeManager.CSharpSignature (method), na.Name.Value);
+ }
+ } else if (arguments[name_index] != a) {
+ if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
+ Report.SymbolRelatedToPreviousError (DeclaringType);
+ else
+ Report.SymbolRelatedToPreviousError (best_candidate);
+
+ Report.Error (1744, na.Name.Location,
+ "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
+ na.Name.Value);
+ }
+ }
}
if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
//
// Fill not provided arguments required by params modifier
//
- int param_count = GetApplicableParametersCount (method, pd);
if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
if (arguments == null)
- arguments = new ArrayList (1);
+ arguments = new Arguments (1);
pt = pd.Types [param_count - 1];
pt = TypeManager.GetElementType (pt);
instance = InstanceExpression.CreateExpressionTree (ec);
}
- ArrayList args = new ArrayList (2);
- args.Add (new Argument (instance));
- args.Add (new Argument (CreateTypeOfExpression ()));
+ Arguments args = Arguments.CreateForExpressionTree (ec, null,
+ instance,
+ CreateTypeOfExpression ());
+
return CreateExpressionFactoryCall ("Field", args);
}
out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
if (InstanceExpression != EmptyExpression.Null)
- InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc);
+ InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
}
} else {
ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
if (!prepared)
EmitInstance (ec, false);
- IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
- if (ff != null) {
- ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
- ig.Emit (OpCodes.Ldflda, ff.Element);
+ // Optimization for build-in types
+ // TODO: Iterators don't set current container
+ if (TypeManager.IsStruct (type) && type == ec.DeclContainer.TypeBuilder && ec.CurrentIterator == null) {
+ LoadFromPtr (ig, type);
} else {
- if (is_volatile)
- ig.Emit (OpCodes.Volatile);
+ IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
+ if (ff != null) {
+ ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
+ ig.Emit (OpCodes.Ldflda, ff.Element);
+ } else {
+ if (is_volatile)
+ ig.Emit (OpCodes.Volatile);
- ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ());
+ ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ());
+ }
}
}
public override Expression CreateExpressionTree (EmitContext ec)
{
- ArrayList args;
+ Arguments args;
if (IsSingleDimensionalArrayLength ()) {
- args = new ArrayList (1);
+ args = new Arguments (1);
args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
return CreateExpressionFactoryCall ("ArrayLength", args);
}
return null;
}
- args = new ArrayList (2);
+ args = new Arguments (2);
if (InstanceExpression == null)
args.Add (new Argument (new NullLiteral (loc)));
else
InstanceExpression = InstanceExpression.DoResolve (ec);
if (lvalue_instance && InstanceExpression != null)
- InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
+ InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess);
if (InstanceExpression == null)
return false;
my_source = temp;
}
- ArrayList args = new ArrayList (1);
- args.Add (new Argument (my_source, Argument.AType.Expression));
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (my_source));
Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared);
public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
{
- ArrayList args = new ArrayList (1);
- args.Add (new Argument (source, Argument.AType.Expression));
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (source));
Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc);
}
}