}
IVariable variable = Expr as IVariable;
- if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+ bool is_fixed = variable != null && variable.VerifyFixed (false);
+
+ if (!ec.InFixedInitializer && !is_fixed) {
Error (212, "You can only take the address of an unfixed expression inside " +
"of a fixed statement initializer");
return null;
}
- if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+ if (ec.InFixedInitializer && is_fixed) {
Error (213, "You can not fix an already fixed expression");
return null;
}
// after semantic analysis (this is so we can take the address
// of an indirection).
//
- public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+ public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
Expression expr;
LocalTemporary temporary;
bool prepared;
{
return "*(" + expr + ")";
}
+
+ #region IVariable Members
+
+ public VariableInfo VariableInfo {
+ get {
+ return null;
+ }
+ }
+
+ public bool VerifyFixed (bool is_expression)
+ {
+ return true;
+ }
+
+ #endregion
}
/// <summary>
//
left.Emit (ec);
ig.Emit (OpCodes.Conv_I);
- right.Emit (ec);
- if (size != 1){
- if (size == 0)
- ig.Emit (OpCodes.Sizeof, element);
- else
- IntLiteral.EmitInt (ig, size);
- if (rtype == TypeManager.int64_type)
- ig.Emit (OpCodes.Conv_I8);
- else if (rtype == TypeManager.uint64_type)
- ig.Emit (OpCodes.Conv_U8);
- ig.Emit (OpCodes.Mul);
+
+ Constant right_const = right as Constant;
+ if (right_const != null && size != 0) {
+ Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size), right_const, loc);
+ if (ex == null)
+ return;
+ ex.Emit (ec);
+ } else {
+ right.Emit (ec);
+ if (size != 1){
+ if (size == 0)
+ ig.Emit (OpCodes.Sizeof, element);
+ else
+ IntLiteral.EmitInt (ig, size);
+ if (rtype == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_I8);
+ else if (rtype == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Conv_U8);
+ ig.Emit (OpCodes.Mul);
+ }
}
if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
Expression expr;
MethodBase method = null;
- static Hashtable method_parameter_cache;
-
- static Invocation ()
- {
- method_parameter_cache = new PtrHashtable ();
- }
-
//
// arguments is an ArrayList, but we do not want to typecast,
// as it might be null.
}
}
- /// <summary>
- /// Returns the Parameters (a ParameterData interface) for the
- /// Method `mb'
- /// </summary>
- public static ParameterData GetParameterData (MethodBase mb)
- {
- object pd = method_parameter_cache [mb];
- object ip;
-
- if (pd != null)
- return (ParameterData) pd;
-
- ip = TypeManager.LookupParametersByBuilder (mb);
- if (ip != null){
- method_parameter_cache [mb] = ip;
-
- return (ParameterData) ip;
- } else {
- ReflectionParameters rp = new ReflectionParameters (mb);
- method_parameter_cache [mb] = rp;
-
- return (ParameterData) rp;
- }
- }
-
/// <summary>
/// Determines "better conversion" as specified in 7.4.2.3
///
MethodBase candidate, bool candidate_params,
MethodBase best, bool best_params, Location loc)
{
- ParameterData candidate_pd = GetParameterData (candidate);
- ParameterData best_pd = GetParameterData (best);
+ ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
+ ParameterData best_pd = TypeManager.GetParameterData (best);
- int cand_count = candidate_pd.Count;
-
- //
- // If there is no best method, than this one
- // is better, however, if we already found a
- // best method, we cant tell. This happens
- // if we have:
- //
- // interface IFoo {
- // void DoIt ();
- // }
- //
- // interface IBar {
- // void DoIt ();
- // }
- //
- // interface IFooBar : IFoo, IBar {}
- //
- // We cant tell if IFoo.DoIt is better than IBar.DoIt
- //
- // However, we have to consider that
- // Trim (); is better than Trim (params char[] chars);
- //
- if (cand_count == 0 && argument_count == 0)
- return !candidate_params && best_params;
-
- if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
- (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
- if (cand_count != argument_count)
- return false;
-
bool better_at_least_one = false;
- bool is_equal = true;
-
+ bool same = true;
for (int j = 0; j < argument_count; ++j) {
Argument a = (Argument) args [j];
if (best_params)
bt = TypeManager.GetElementType (bt);
- if (!ct.Equals (bt))
- is_equal = false;
+ if (ct.Equals (bt))
+ continue;
+ same = false;
Type better = BetterConversion (ec, a, ct, bt, loc);
// for each argument, the conversion to 'ct' should be no worse than
// the conversion to 'bt'.
better_at_least_one = true;
}
- //
- // If a method (in the normal form) with the
- // same signature as the expanded form of the
- // current best params method already exists,
- // the expanded form is not applicable so we
- // force it to select the candidate
- //
- if (!candidate_params && best_params && cand_count == argument_count)
- return true;
+ if (better_at_least_one)
+ return true;
+
+ if (!same)
+ return false;
//
// If two methods have equal parameter types, but
// only one of them is generic, the non-generic one wins.
//
- if (is_equal) {
- if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
- return true;
- else if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
- return false;
+ if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
+ return true;
+ else if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
+ return false;
+
+ //
+ // Note that this is not just an optimization. This handles the case
+ //
+ // Add (float f1, float f2, float f3);
+ // Add (params decimal [] foo);
+ //
+ // The call Add (3, 4, 5) should be ambiguous. Without this check, the
+ // first candidate would've chosen as better.
+ //
+ if (candidate_params == best_params) {
+ //
+ // We need to handle the case of a virtual function and its override.
+ // The override is ignored during 'applicable_type' calculation. However,
+ // it should be chosen over the base virtual function, especially when handling
+ // value types.
+ //
+ return IsAncestralType (best.DeclaringType, candidate.DeclaringType);
}
- return better_at_least_one;
+ //
+ // This handles the following cases:
+ //
+ // Trim () is better than Trim (params char[] chars)
+ // Concat (string s1, string s2, string s3) is better than
+ // Concat (string s1, params string [] srest)
+ //
+ return !candidate_params && best_params;
}
public static string FullMethodDesc (MethodBase mb)
sb.Append (".");
sb.Append (mb.Name);
- ParameterData pd = GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
int count = pd.Count;
sb.Append (" (");
int arg_count, MethodBase candidate,
bool do_varargs)
{
- ParameterData pd = GetParameterData (candidate);
+ ParameterData pd = TypeManager.GetParameterData (candidate);
int pd_count = pd.Count;
static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count,
MethodBase candidate)
{
- ParameterData pd = GetParameterData (candidate);
+ ParameterData pd = TypeManager.GetParameterData (candidate);
if (arg_count != pd.Count)
return false;
candidates.Add (methods [i]);
+ //
+ // Methods marked 'override' don't take part in 'applicable_type'
+ // computation.
+ //
+ if (!me.IsBase &&
+ methods [i].IsVirtual &&
+ (methods [i].Attributes & MethodAttributes.NewSlot) == 0)
+ continue;
+
if (applicable_type == null)
applicable_type = decl_type;
else if (applicable_type != decl_type) {
int candidate_top = candidates.Count;
- if (candidate_top == 0) {
+ if (applicable_type == null) {
//
// Okay so we have failed to find anything so we
// return by providing info about the closest match
//
for (int i = 0; i < methods.Length; ++i) {
MethodBase c = (MethodBase) methods [i];
- ParameterData pd = GetParameterData (c);
+ ParameterData pd = TypeManager.GetParameterData (c);
if (pd.Count != arg_count)
continue;
for (int i = 0; i < methods.Length; ++i) {
MethodBase c = methods [i];
- ParameterData pd = GetParameterData (c);
+ ParameterData pd = TypeManager.GetParameterData (c);
if (pd.Count != arg_count)
continue;
int j = finalized; // where to put the next finalized candidate
int k = finalized; // where to put the next undiscarded candidate
for (int i = finalized; i < candidate_top; ++i) {
- Type decl_type = ((MethodBase) candidates[i]).DeclaringType;
+ MethodBase candidate = (MethodBase) candidates [i];
+ Type decl_type = candidate.DeclaringType;
if (decl_type == applicable_type) {
- candidates[k++] = candidates[j];
- candidates[j++] = candidates[i];
+ candidates [k++] = candidates [j];
+ candidates [j++] = candidates [i];
continue;
}
IsAncestralType (decl_type, next_applicable_type))
continue;
- candidates[k++] = candidates[i];
+ candidates [k++] = candidates [i];
+
+#if false
+ //
+ // Methods marked 'override' don't take part in 'applicable_type'
+ // computation.
+ //
+ if (!me.IsBase &&
+ candidate.IsVirtual &&
+ (candidate.Attributes & MethodAttributes.NewSlot) == 0)
+ continue;
+#endif
if (next_applicable_type == null ||
IsAncestralType (next_applicable_type, decl_type))
// Now we actually find the best method
//
- method = (MethodBase) candidates[0];
+ method = (MethodBase) candidates [0];
method_params = candidate_to_form != null && candidate_to_form.Contains (method);
for (int ix = 1; ix < candidate_top; ix++){
MethodBase candidate = (MethodBase) candidates [ix];
+
+ if (candidate == method)
+ continue;
+
bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
if (BetterFunction (ec, Arguments, arg_count,
Type delegate_type, bool may_fail,
Location loc)
{
- ParameterData pd = GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
int pd_count = pd.Count;
for (int j = 0; j < arg_count; j++) {
{
ParameterData pd;
if (mb != null)
- pd = GetParameterData (mb);
+ pd = TypeManager.GetParameterData (mb);
else
pd = null;
static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
ArrayList arguments)
{
- ParameterData pd = GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
if (arguments == null)
return new Type [0];
if ((block != null) && (block.ThisVariable != null))
variable_info = block.ThisVariable.VariableInfo;
+ if (ec.CurrentAnonymousMethod != null)
+ ec.CaptureThis ();
+
return true;
}
object real_value = ((Constant) c.Expr).GetValue ();
- return Constantify (real_value, t);
+ Expression exp = Constantify (real_value, t);
+
+ if (left_is_explicit && !left_is_type && !IdenticalNameAndTypeName (ec, left_original, left, loc)) {
+ Report.SymbolRelatedToPreviousError (c);
+ error176 (loc, c.GetSignatureForError ());
+ return null;
+ }
+
+ return exp;
}
}
}
public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+ {
+ return ResolveNamespaceOrType (ec, false);
+ }
+
+ public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
{
FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec);
FullNamedExpression retval = ns.Lookup (ec.DeclSpace, lookup_id, loc);
if ((retval != null) && (args != null))
retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec);
- if (retval == null)
+ if (!silent && retval == null)
Report.Error (234, loc, "The type or namespace name `{0}' could not be found in namespace `{1}'", Identifier, ns.FullName);
return retval;
}
Expression member_lookup;
member_lookup = MemberLookupFinal (ec, expr_type, expr_type, lookup_id, loc);
- if (member_lookup == null) {
+ if (!silent && member_lookup == null) {
Report.Error (234, loc, "The type name `{0}' could not be found in type `{1}'",
Identifier, new_expr.FullName);
return null;