(other == TypeManager.int32_type) ||
(other == TypeManager.int64_type))
Error_OperatorAmbiguous (loc, oper, l, r);
+ else {
+ left = ForceConversion (ec, left, TypeManager.uint64_type);
+ right = ForceConversion (ec, right, TypeManager.uint64_type);
+ }
type = TypeManager.uint64_type;
} else if (IsOfType (ec, l, r, TypeManager.int64_type, check_user_conv)){
//
Type l = left.Type;
Type r = right.Type;
- bool overload_failed = false;
-
//
// Special cases: string comapred to null
//
if (oper == Operator.Equality || oper == Operator.Inequality){
- if ((l == TypeManager.string_type && (right is NullLiteral)) ||
- (r == TypeManager.string_type && (left is NullLiteral))){
+ if ((!TypeManager.IsValueType (l) && (right is NullLiteral)) ||
+ (!TypeManager.IsValueType (r) && (left is NullLiteral))) {
Type = TypeManager.bool_type;
return this;
MethodInfo mi = (MethodInfo) method;
return new BinaryMethod (mi.ReturnType, method, args);
- } else {
- overload_failed = true;
}
}
}
if (r == l)
return new PointerArithmetic (
false, left, right, TypeManager.int64_type,
- loc);
+ loc).Resolve (ec);
} else {
Expression t = Make32or64 (ec, right);
if (t != null)
- return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc);
+ return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc).Resolve (ec);
}
} else if (r.IsPointer && oper == Operator.Addition){
Expression t = Make32or64 (ec, left);
if (t != null)
- return new PointerArithmetic (true, right, t, r, loc);
+ return new PointerArithmetic (true, right, t, r, loc).Resolve (ec);
}
}
}
}
- //
- // We are dealing with numbers
- //
- if (overload_failed){
- Error_OperatorCannotBeApplied ();
- return null;
- }
-
//
// This will leave left or right set to null if there is an error
//
public class StringConcat : Expression {
ArrayList operands;
bool invalid = false;
-
+ bool emit_conv_done = false;
+ //
+ // Are we also concating objects?
+ //
+ bool is_strings_only = true;
public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
{
{
MethodInfo concat_method = null;
- //
- // Are we also concating objects?
- //
- bool is_strings_only = true;
-
//
// Do conversion to arguments; check for strings only
//
- for (int i = 0; i < operands.Count; i ++) {
- Expression e = (Expression) operands [i];
- is_strings_only &= e.Type == TypeManager.string_type;
- }
- for (int i = 0; i < operands.Count; i ++) {
- Expression e = (Expression) operands [i];
+ // This can get called multiple times, so we have to deal with that.
+ if (!emit_conv_done) {
+ emit_conv_done = true;
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+ is_strings_only &= e.Type == TypeManager.string_type;
+ }
- if (! is_strings_only && e.Type == TypeManager.string_type) {
- // need to make sure this is an object, because the EmitParams
- // method might look at the type of this expression, see it is a
- // string and emit a string [] when we want an object [];
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
- e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+ if (! is_strings_only && e.Type == TypeManager.string_type) {
+ // need to make sure this is an object, because the EmitParams
+ // method might look at the type of this expression, see it is a
+ // string and emit a string [] when we want an object [];
+
+ e = new EmptyCast (e, TypeManager.object_type);
+ }
+ operands [i] = new Argument (e, Argument.AType.Expression);
}
- operands [i] = new Argument (e, Argument.AType.Expression);
}
//
public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t, Location loc)
{
type = t;
- eclass = ExprClass.Variable;
this.loc = loc;
left = l;
right = r;
public override Expression DoResolve (EmitContext ec)
{
- //
- // We are born fully resolved
- //
+ eclass = ExprClass.Variable;
+
+ if (left.Type == TypeManager.void_ptr_type) {
+ Error (242, "The operation in question is undefined on void pointers");
+ return null;
+ }
+
return this;
}
{
Type op_type = left.Type;
ILGenerator ig = ec.ig;
- int size = GetTypeSize (TypeManager.GetElementType (op_type));
+ Type element = TypeManager.GetElementType (op_type);
+ int size = GetTypeSize (element);
Type rtype = right.Type;
if (rtype.IsPointer){
if (size != 1){
if (size == 0)
- ig.Emit (OpCodes.Sizeof, op_type);
+ ig.Emit (OpCodes.Sizeof, element);
else
IntLiteral.EmitInt (ig, size);
ig.Emit (OpCodes.Div);
right.Emit (ec);
if (size != 1){
if (size == 0)
- ig.Emit (OpCodes.Sizeof, op_type);
+ ig.Emit (OpCodes.Sizeof, element);
else
IntLiteral.EmitInt (ig, size);
if (rtype == TypeManager.int64_type)
else if (rtype == TypeManager.uint64_type)
ig.Emit (OpCodes.Conv_U8);
ig.Emit (OpCodes.Mul);
- ig.Emit (OpCodes.Conv_I);
}
+
+ if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Conv_I);
+
if (is_add)
ig.Emit (OpCodes.Add);
else
if (e != null) {
local_info.Used = true;
eclass = ExprClass.Value;
- return e;
+ return e.Resolve (ec);
}
VariableInfo variable_info = local_info.VariableInfo;
if (argument_type == q)
return 0;
- //
- // Now probe whether an implicit constant expression conversion
- // can be used.
- //
- // An implicit constant expression conversion permits the following
- // conversions:
- //
- // * A constant-expression of type `int' can be converted to type
- // sbyte, byute, short, ushort, uint, ulong provided the value of
- // of the expression is withing the range of the destination type.
- //
- // * A constant-expression of type long can be converted to type
- // ulong, provided the value of the constant expression is not negative
- //
- // FIXME: Note that this assumes that constant folding has
- // taken place. We dont do constant folding yet.
- //
-
- if (argument_expr is IntConstant){
- IntConstant ei = (IntConstant) argument_expr;
- int value = ei.Value;
-
- if (p == TypeManager.sbyte_type){
- if (value >= SByte.MinValue && value <= SByte.MaxValue)
- return 1;
- } else if (p == TypeManager.byte_type){
- if (q == TypeManager.sbyte_type &&
- value >= SByte.MinValue && value <= SByte.MaxValue)
- return 0;
- else if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
- return 1;
- } else if (p == TypeManager.short_type){
- if (value >= Int16.MinValue && value <= Int16.MaxValue)
- return 1;
- } else if (p == TypeManager.ushort_type){
- if (q == TypeManager.short_type &&
- value >= Int16.MinValue && value <= Int16.MaxValue)
- return 0;
- else if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
- return 1;
- } else if (p == TypeManager.int32_type){
- if (value >= Int32.MinValue && value <= Int32.MaxValue)
- return 1;
- } else if (p == TypeManager.uint32_type){
- //
- // we can optimize this case: a positive int32
- // always fits on a uint32
- //
- if (value >= 0)
- return 1;
- } else if (p == TypeManager.uint64_type){
- //
- // we can optimize this case: a positive int32
- // always fits on a uint64
- //
-
- //
- // This special case is needed because csc behaves like this.
- // int -> uint is better than int -> ulong!
- //
- if (q == TypeManager.uint32_type)
- return 0;
-
- if (q == TypeManager.int64_type)
- return 0;
- else if (value >= 0)
- return 1;
- } else if (p == TypeManager.int64_type){
- return 1;
- }
- } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){
- LongConstant lc = (LongConstant) argument_expr;
-
- if (p == TypeManager.uint64_type){
- if (lc.Value > 0)
- return 1;
- }
- }
-
if (q == null) {
Expression tmp = Convert.ImplicitConversion (ec, argument_expr, p, loc);
/// Determines if the candidate method, if a params method, is applicable
/// in its expanded form to the given set of arguments
/// </summary>
- static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
+ static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
+ MethodBase candidate, bool do_varargs)
{
int arg_count;
return false;
int count = pd_count - 1;
-
- bool is_varargs = false;
- if (pd.ParameterModifier (count) == Parameter.Modifier.ARGLIST)
- is_varargs = true;
- else if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS)
- return false;
+ if (do_varargs) {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
+ return false;
+ if (pd_count != arg_count)
+ return false;
+ } else {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS)
+ return false;
+ }
if (count > arg_count)
return false;
}
- if (is_varargs)
+ if (do_varargs) {
+ Argument a = (Argument) arguments [count];
+ if (!(a.Expr is Arglist))
+ return false;
+
return true;
+ }
Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
for (int i = pd_count - 1; i < arg_count; i++) {
Argument a = (Argument) arguments [i];
-
+
if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
return false;
}
candidates.Add (candidate);
applicable_type = candidate.DeclaringType;
found_applicable = true;
- } else if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
+ } else if (IsParamsMethodApplicable (ec, Arguments, candidate, false)) {
+ if (candidate_to_form == null)
+ candidate_to_form = new PtrHashtable ();
+
+ // Candidate is applicable in expanded form
+ candidates.Add (candidate);
+ applicable_type = candidate.DeclaringType;
+ found_applicable = true;
+ candidate_to_form [candidate] = candidate;
+ } else if (IsParamsMethodApplicable (ec, Arguments, candidate, true)) {
if (candidate_to_form == null)
candidate_to_form = new PtrHashtable ();
Expression tmp = (Expression) o;
tmp = tmp.Resolve (ec);
if (tmp == null)
- continue;
+ return false;
// Console.WriteLine ("I got: " + tmp);
// Handle initialization from vars, fields etc.
if (type == null)
return false;
-
- underlying_type = type;
- if (underlying_type.IsArray)
- underlying_type = TypeManager.GetElementType (underlying_type);
+
+ if (!type.IsArray) {
+ Error (622, "Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
+ return false;
+ }
+ underlying_type = TypeManager.GetElementType (type);
dimensions = type.GetArrayRank ();
return true;
return null;
}
+ if (typearg.IsPointer && !ec.InUnsafe){
+ UnsafeError (loc);
+ return null;
+ }
CheckObsoleteAttribute (typearg);
type = TypeManager.type_type;
"type name instead");
}
- static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
+ public static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
{
SimpleName sn = left_original as SimpleName;
if (sn == null || left == null || left.Type.Name != sn.Name)
//
Expression original = expr;
- expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
+ expr = expr.Resolve (ec, flags | ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis);
if (expr == null)
return null;
return true;
}
- Expression MakePointerAccess ()
+ Expression MakePointerAccess (EmitContext ec)
{
Type t = Expr.Type;
}
Expression p;
- p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc);
- return new Indirection (p, loc);
+ p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc).Resolve (ec);
+ if (p == null)
+ return null;
+ return new Indirection (p, loc).Resolve (ec);
}
public override Expression DoResolve (EmitContext ec)
if (t.IsArray)
return (new ArrayAccess (this, loc)).Resolve (ec);
else if (t.IsPointer)
- return MakePointerAccess ();
+ return MakePointerAccess (ec);
else
return (new IndexerAccess (this, loc)).Resolve (ec);
}
if (t.IsArray)
return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
else if (t.IsPointer)
- return MakePointerAccess ();
+ return MakePointerAccess (ec);
else
return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
}
//Console.WriteLine (new System.Diagnostics.StackTrace ());
is_stobj = false;
t = TypeManager.TypeToCoreType (t);
- if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type)
+ if (TypeManager.IsEnumType (t))
t = TypeManager.EnumToUnderlying (t);
if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
t == TypeManager.bool_type)
pe.IsBase = true;
}
+
+ if (e is MethodGroupExpr)
+ ((MethodGroupExpr) e).IsBase = true;
return e;
}
return null;
}
+ Constant c = count as Constant;
+ // TODO: because we don't have property IsNegative
+ if (c != null && c.ConvertToUInt () == null) {
+ // "Cannot use a negative size with stackalloc"
+ Report.Error_T (247, loc);
+ return null;
+ }
+
if (ec.CurrentBranching.InCatch () ||
ec.CurrentBranching.InFinally (true)) {
Error (255,