mg.EmitCall (ec, arguments);
}
- [Obsolete ("It may not be compatible with expression trees")]
- static public UserOperatorCall MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
- Expression e, Location loc)
- {
- ArrayList args;
-
- args = new ArrayList (1);
- Argument a = new Argument (e, Argument.AType.Expression);
-
- // We need to resolve the arguments before sending them in !
- if (!a.Resolve (ec, loc))
- return null;
-
- args.Add (a);
- mg = mg.OverloadResolve (ec, ref args, false, loc);
-
- if (mg == null)
- return null;
-
- return new UserOperatorCall (mg, args, null, loc);
- }
-
public MethodGroupExpr Method {
get { return mg; }
}
// </summary>
Constant TryReduceConstant (EmitContext ec, Constant e)
{
+ if (e is EmptyConstantCast)
+ return TryReduceConstant (ec, ((EmptyConstantCast) e).child);
+
if (e is SideEffectConstant) {
Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
return r == null ? null : new SideEffectConstant (r, e, r.Location);
public override Expression DoResolve (EmitContext ec)
{
if (Oper == Operator.AddressOf) {
- Expr = Expr.DoResolveLValue (ec, new EmptyExpression ());
-
- if (Expr == null || Expr.eclass != ExprClass.Variable){
- Error (211, "Cannot take the address of the given expression");
- return null;
- }
-
return ResolveAddressOf (ec);
}
Expression ResolveAddressOf (EmitContext ec)
{
- if (!ec.InUnsafe) {
+ if (!ec.InUnsafe)
UnsafeError (loc);
+
+ Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
+ if (Expr == null || Expr.eclass != ExprClass.Variable) {
+ Error (211, "Cannot take the address of the given expression");
return null;
}
return null;
}
- IVariable variable = Expr as IVariable;
- if (variable != null && variable.IsFixed) {
- if (ec.InFixedInitializer) {
- Error (213, "You cannot use the fixed statement to take the address of an already fixed expression");
- return null;
- }
- } else {
- if (!ec.InFixedInitializer) {
- Error (212, "You can only take the address of unfixed expression inside of a fixed statement initializer");
- return null;
- }
- }
+ IVariableReference vr = Expr as IVariableReference;
+ bool is_fixed;
+ if (vr != null) {
+ VariableInfo vi = vr.VariableInfo;
+ if (vi != null) {
+ if (vi.LocalInfo != null)
+ vi.LocalInfo.Used = true;
- LocalVariableReference lr = Expr as LocalVariableReference;
- if (lr != null) {
- if (lr.IsHoisted) {
- AnonymousMethodBody.Error_AddressOfCapturedVar (lr.Name, loc);
- return null;
+ //
+ // A variable is considered definitely assigned if you take its address.
+ //
+ vi.SetAssigned (ec);
}
- lr.local_info.AddressTaken = true;
- lr.local_info.Used = true;
- }
- ParameterReference pr = Expr as ParameterReference;
- if ((pr != null) && pr.IsHoisted) {
- AnonymousMethodBody.Error_AddressOfCapturedVar (pr.Name, loc);
- return null;
+ is_fixed = vr.IsFixedVariable;
+ vr.SetHasAddressTaken ();
+
+ if (vr.IsHoisted) {
+ AnonymousMethodExpression.Error_AddressOfCapturedVar (vr, loc);
+ }
+ } else {
+ //
+ // A pointer-indirection is always fixed
+ //
+ is_fixed = Expr is Indirection;
}
- // According to the specs, a variable is considered definitely assigned if you take
- // its address.
- if ((variable != null) && (variable.VariableInfo != null)) {
- variable.VariableInfo.SetAssigned (ec);
+ if (!is_fixed && !ec.InFixedInitializer) {
+ Error (212, "You can only take the address of unfixed expression inside of a fixed statement initializer");
}
type = TypeManager.GetPointerType (Expr.Type);
// after semantic analysis (this is so we can take the address
// of an indirection).
//
- public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
+ public class Indirection : Expression, IMemoryLocation, IAssignMethod {
Expression expr;
LocalTemporary temporary;
bool prepared;
return null;
}
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ Indirection target = (Indirection) t;
+ target.expr = expr.Clone (clonectx);
+ }
+
public override void Emit (EmitContext ec)
{
if (!prepared)
return null;
}
+ if (expr.Type == TypeManager.void_ptr_type) {
+ Error (242, "The operation in question is undefined on void pointers");
+ return null;
+ }
+
type = TypeManager.GetElementType (expr.Type);
eclass = ExprClass.Variable;
return this;
}
-
+
public override string ToString ()
{
return "*(" + expr + ")";
}
-
- #region IVariable Members
-
- public VariableInfo VariableInfo {
- get { return null; }
- }
-
- //
- // A pointer-indirection is always fixed.
- //
- public bool IsFixed {
- get { return true; }
- }
-
- #endregion
}
/// <summary>
Expression ResolveOperator (EmitContext ec)
{
- Type expr_type = expr.Type;
+ type = expr.Type;
//
// Step 1: Perform Operator Overload location
//
- Expression mg;
+ MethodGroupExpr mg;
string op_name;
if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
else
op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
- mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+ mg = MemberLookup (ec.ContainerType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
if (mg != null) {
- method = UserOperatorCall.MakeSimpleCall (
- ec, (MethodGroupExpr) mg, expr, loc);
+ ArrayList args = new ArrayList (1);
+ args.Add (new Argument (expr, Argument.AType.Expression));
+ mg = mg.OverloadResolve (ec, ref args, false, loc);
+ if (mg == null)
+ return null;
- type = method.Type;
- } else if (!IsIncrementableNumber (expr_type)) {
+ method = new UserOperatorCall (mg, args, null, loc);
+ Convert.ImplicitConversionRequired (ec, method, type, loc);
+ return this;
+ }
+
+ if (!IsIncrementableNumber (type)) {
Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
- TypeManager.CSharpName (expr_type) + "'");
- return null;
+ TypeManager.CSharpName (type) + "'");
+ return null;
}
//
// should be an expression that is classified as a variable,
// a property access or an indexer access
//
- type = expr_type;
- if (expr.eclass == ExprClass.Variable){
- LocalVariableReference var = expr as LocalVariableReference;
- if ((var != null) && var.IsReadOnly) {
- Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
- return null;
- }
- } else if (expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess){
- expr = expr.ResolveLValue (ec, this, Location);
- if (expr == null)
- return null;
+ if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
+ expr = expr.ResolveLValue (ec, expr, Location);
} else {
Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
- return null;
}
return this;
expr = expr.Resolve (ec);
if (expr == null)
return null;
+
+ if ((probe_type_expr.Type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+ Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type",
+ OperatorName);
+ }
if (expr.Type.IsPointer || probe_type_expr.Type.IsPointer) {
Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type",
Type d = expr.Type;
bool d_is_nullable = false;
- if (expr is Constant) {
- //
- // If E is a method group or the null literal, of if the type of E is a reference
- // type or a nullable type and the value of E is null, the result is false
- //
- if (expr.IsNull)
- return CreateConstantResult (false);
- } else if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
+ //
+ // If E is a method group or the null literal, or if the type of E is a reference
+ // type or a nullable type and the value of E is null, the result is false
+ //
+ if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
+ return CreateConstantResult (false);
+
+ if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
d = TypeManager.GetTypeArguments (d) [0];
d_is_nullable = true;
}
return CreateConstantResult (false);
if (constraints.IsValueType && !d.IsValueType)
- return CreateConstantResult (false);
+ return CreateConstantResult (TypeManager.IsEqual (d, t));
}
- expr = new BoxedCast (expr, d);
+ if (!TypeManager.IsReferenceType (expr.Type))
+ expr = new BoxedCast (expr, d);
+
return this;
#else
return null;
#endif
}
- static void Error_CannotConvertType (Type source, Type target, Location loc)
- {
- Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
- TypeManager.CSharpName (source),
- TypeManager.CSharpName (target));
- }
-
public override Expression DoResolve (EmitContext ec)
{
if (resolved_type == null) {
eclass = ExprClass.Value;
Type etype = expr.Type;
- if (type.IsValueType && !TypeManager.IsNullableType (type)) {
- Report.Error (77, loc, "The `as' operator cannot be used with a non-nullable value type `{0}'",
- TypeManager.CSharpName (type));
- return null;
-
- }
-
-#if GMCS_SOURCE
- //
- // If the type is a type parameter, ensure
- // that it is constrained by a class
- //
- TypeParameterExpr tpe = probe_type_expr as TypeParameterExpr;
- if (tpe != null){
- GenericConstraints constraints = tpe.TypeParameter.GenericConstraints;
- bool error = false;
-
- if (constraints == null)
- error = true;
- else {
- if (!constraints.HasClassConstraint)
- if ((constraints.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == 0)
- error = true;
- }
- if (error){
+ if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) {
+ if (probe_type_expr is TypeParameterExpr) {
Report.Error (413, loc,
- "The as operator requires that the `{0}' type parameter be constrained by a class",
- probe_type_expr.GetSignatureForError ());
- return null;
+ "The `as' operator cannot be used with a non-reference type parameter `{0}'",
+ probe_type_expr.GetSignatureForError ());
+ } else {
+ Report.Error (77, loc,
+ "The `as' operator cannot be used with a non-nullable value type `{0}'",
+ TypeManager.CSharpName (type));
}
+ return null;
}
-#endif
+
if (expr.IsNull && TypeManager.IsNullableType (type)) {
return Nullable.LiftedNull.CreateFromExpression (this);
}
return this;
}
- Error_CannotConvertType (etype, type, loc);
+ Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
+ TypeManager.CSharpName (etype), TypeManager.CSharpName (type));
+
return null;
}
get { return "as"; }
}
- public override bool GetAttributableValue (Type value_type, out object value)
+ public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
{
- return expr.GetAttributableValue (value_type, out value);
+ return expr.GetAttributableValue (ec, value_type, out value);
}
}
this.target_type = cast_type;
this.expr = expr;
this.loc = loc;
-
- if (target_type == TypeManager.system_void_expr)
- Error_VoidInvalidInTheContext (loc);
}
public Expression TargetType {
type = texpr.Type;
- if (type == TypeManager.void_type) {
- Error_VoidInvalidInTheContext (loc);
- return null;
+ if ((type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+ Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type");
}
- if (TypeManager.IsGenericParameter (type)) {
- GenericConstraints constraints = TypeManager.GetTypeParameterConstraints(type);
- if (constraints != null && constraints.IsReferenceType)
- return new EmptyConstantCast (new NullLiteral (Location), type);
- } else {
- Constant c = New.Constantify (type);
- if (c != null)
- return c;
+ if (type.IsPointer)
+ return new NullLiteral (Location).ConvertImplicitly (type);
+
+ if (TypeManager.IsReferenceType (type)) {
+ return new EmptyConstantCast (new NullLiteral (Location), type);
- if (!TypeManager.IsValueType (type))
- return new EmptyConstantCast (new NullLiteral (Location), type);
+ // TODO: ET needs
+ // return ReducedExpression.Create (new NullLiteral (Location), this);
}
+
+ Constant c = New.Constantify (type);
+ if (c != null)
+ return c;
+
eclass = ExprClass.Variable;
return this;
}
Convert.ImplicitConversionExists (ec, rexpr, right);
}
- public PredefinedOperator ResolveBetterOperator (EmitContext ec, Expression lexpr, Expression rexpr, PredefinedOperator best_operator)
+ public PredefinedOperator ResolveBetterOperator (EmitContext ec, PredefinedOperator best_operator)
{
int result = 0;
if (left != null && best_operator.left != null) {
//
// When second arguments are same as the first one, the result is same
//
- if (left != right || best_operator.left != best_operator.right) {
+ if (right != null && (left != right || best_operator.left != best_operator.right)) {
result |= MethodGroupExpr.BetterTypeConversion (ec, best_operator.right, right);
}
{
}
+ public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask, Type retType)
+ : base (ltype, rtype, op_mask, retType)
+ {
+ }
+
public PredefinedPointerOperator (Type type, Operator op_mask, Type return_type)
: base (type, op_mask, return_type)
{
Type r_type = ReturnType;
if (r_type == null) {
- r_type = b.left.Type;
- if (r_type == null)
+ if (left == null)
+ r_type = b.left.Type;
+ else
r_type = b.right.Type;
}
// T* operator + (long y, T *x);
// T* operator + (ulong y, T *x);
//
- temp.Add (new PredefinedPointerOperator (TypeManager.int32_type, null, Operator.AdditionMask));
- temp.Add (new PredefinedPointerOperator (TypeManager.uint32_type, null, Operator.AdditionMask));
- temp.Add (new PredefinedPointerOperator (TypeManager.int64_type, null, Operator.AdditionMask));
- temp.Add (new PredefinedPointerOperator (TypeManager.uint64_type, null, Operator.AdditionMask));
+ temp.Add (new PredefinedPointerOperator (TypeManager.int32_type, null, Operator.AdditionMask, null));
+ temp.Add (new PredefinedPointerOperator (TypeManager.uint32_type, null, Operator.AdditionMask, null));
+ temp.Add (new PredefinedPointerOperator (TypeManager.int64_type, null, Operator.AdditionMask, null));
+ temp.Add (new PredefinedPointerOperator (TypeManager.uint64_type, null, Operator.AdditionMask, null));
//
// long operator - (T* x, T *y)
return null;
}
- if (rc != null) {
- right = left;
- lc = rc;
- }
-
+ //
// The result is a constant with side-effect
- return new SideEffectConstant (lc, right, loc);
+ //
+ Constant side_effect = rc == null ?
+ new SideEffectConstant (lc, right, loc) :
+ new SideEffectConstant (rc, left, loc);
+
+ return ReducedExpression.Create (side_effect, this);
}
}
Expression ltemp = left;
Expression rtemp = right;
Type underlying_type;
+ Expression expr;
+
+ if ((oper & Operator.ComparisonMask | Operator.BitwiseMask) != 0) {
+ if (renum) {
+ expr = Convert.ImplicitConversion (ec, left, rtype, loc);
+ if (expr != null) {
+ left = expr;
+ ltype = expr.Type;
+ }
+ } else if (lenum) {
+ expr = Convert.ImplicitConversion (ec, right, ltype, loc);
+ if (expr != null) {
+ right = expr;
+ rtype = expr.Type;
+ }
+ }
+ }
if (TypeManager.IsEqual (ltype, rtype)) {
underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
res_type = ltype;
}
- Expression expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
+ expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
if (!is_compound || expr == null)
return expr;
continue;
}
- best_operator = po.ResolveBetterOperator (ec, left, right, best_operator);
+ best_operator = po.ResolveBetterOperator (ec, best_operator);
if (best_operator == null) {
Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
WarnUselessComparison (type);
}
- private bool IsValueOutOfRange (long value, Type type)
+ static bool IsValueOutOfRange (long value, Type type)
{
if (IsTypeUnsigned (type) && value < 0)
return true;
right.Emit (ec);
Type t = left.Type;
- bool is_unsigned = IsUnsigned (t) || IsFloat (t);
+ bool is_float = IsFloat (t);
+ bool is_unsigned = is_float || IsUnsigned (t);
switch (oper){
case Operator.Equality:
case Operator.LessThan:
if (on_true)
- if (is_unsigned)
+ if (is_unsigned && !is_float)
ig.Emit (OpCodes.Blt_Un, target);
else
ig.Emit (OpCodes.Blt, target);
case Operator.GreaterThan:
if (on_true)
- if (is_unsigned)
+ if (is_unsigned && !is_float)
ig.Emit (OpCodes.Bgt_Un, target);
else
ig.Emit (OpCodes.Bgt, target);
case Operator.LessThanOrEqual:
if (on_true)
- if (is_unsigned)
+ if (is_unsigned && !is_float)
ig.Emit (OpCodes.Ble_Un, target);
else
ig.Emit (OpCodes.Ble, target);
case Operator.GreaterThanOrEqual:
if (on_true)
- if (is_unsigned)
+ if (is_unsigned && !is_float)
ig.Emit (OpCodes.Bge_Un, target);
else
ig.Emit (OpCodes.Bge, target);
if (concat != null)
concat.Emit (ec);
}
+
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ foreach (Argument a in arguments)
+ a.Expr.MutateHoistedGenericType (storey);
+ }
}
//
{
MethodInfo method = (MethodInfo)mg;
type = TypeManager.TypeToCoreType (method.ReturnType);
- ParameterData pd = TypeManager.GetParameterData (method);
+ AParametersCollection pd = TypeManager.GetParameterData (method);
if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) {
Report.Error (217, loc,
"A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
ILGenerator ig = ec.ig;
// It must be either array or fixed buffer
- Type element = TypeManager.HasElementType (op_type) ?
- element = TypeManager.GetElementType (op_type) :
- element = AttributeTester.GetFixedBuffer (((FieldExpr)left).FieldInfo).ElementType;
+ Type element;
+ if (TypeManager.HasElementType (op_type)) {
+ element = TypeManager.GetElementType (op_type);
+ } else {
+ FieldExpr fe = left as FieldExpr;
+ if (fe != null)
+ element = AttributeTester.GetFixedBuffer (fe.FieldInfo).ElementType;
+ else
+ element = op_type;
+ }
int size = GetTypeSize (element);
Type rtype = right.Type;
- if (rtype.IsPointer){
+ if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){
//
// handle (pointer - pointer)
//
return null;
eclass = ExprClass.Value;
- if (true_expr.Type == false_expr.Type) {
- type = true_expr.Type;
- if (type == TypeManager.null_type) {
- // TODO: probably will have to implement ConditionalConstant
- // to call method without return constant as well
- Report.Warning (-101, 1, loc, "Conditional expression will always return same value");
- return true_expr;
- }
- } else {
- Expression conv;
- Type true_type = true_expr.Type;
- Type false_type = false_expr.Type;
+ Type true_type = true_expr.Type;
+ Type false_type = false_expr.Type;
+ type = true_type;
- //
- // First, if an implicit conversion exists from true_expr
- // to false_expr, then the result type is of type false_expr.Type
- //
- conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
- if (conv != null){
+ //
+ // First, if an implicit conversion exists from true_expr
+ // to false_expr, then the result type is of type false_expr.Type
+ //
+ if (!TypeManager.IsEqual (true_type, false_type)) {
+ Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
+ if (conv != null) {
//
// Check if both can convert implicitl to each other's type
//
- if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null){
+ if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) {
Error (172,
- "Can not compute type of conditional expression " +
- "as `" + TypeManager.CSharpName (true_expr.Type) +
- "' and `" + TypeManager.CSharpName (false_expr.Type) +
- "' convert implicitly to each other");
+ "Can not compute type of conditional expression " +
+ "as `" + TypeManager.CSharpName (true_expr.Type) +
+ "' and `" + TypeManager.CSharpName (false_expr.Type) +
+ "' convert implicitly to each other");
return null;
}
type = false_type;
true_expr = conv;
- } else if ((conv = Convert.ImplicitConversion(ec, false_expr, true_type,loc))!= null){
- type = true_type;
+ } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) {
false_expr = conv;
} else {
- Report.Error (173, loc, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
+ Report.Error (173, loc,
+ "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
return null;
}
- }
+ }
// Dead code optimalization
- if (expr is BoolConstant){
- BoolConstant bc = (BoolConstant) expr;
-
- Report.Warning (429, 4, bc.Value ? false_expr.Location : true_expr.Location, "Unreachable expression code detected");
- return bc.Value ? true_expr : false_expr;
+ Constant c = expr as Constant;
+ if (c != null){
+ bool is_false = c.IsDefaultValue;
+ Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected");
+ return ReducedExpression.Create (is_false ? false_expr : true_expr, this).Resolve (ec);
}
return this;
}
}
- public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+ public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference {
LocalTemporary temp;
#region Abstract
public abstract HoistedVariable HoistedVariable { get; }
- public abstract bool IsFixed { get; }
+ public abstract bool IsFixedVariable { get; }
public abstract bool IsRef { get; }
+ public abstract string Name { get; }
+ public abstract void SetHasAddressTaken ();
//
// Variable IL data, it has to be protected to encapsulate hoisted variables
return;
}
- ILGenerator ig = ec.ig;
-
if (IsRef)
Variable.Emit (ec);
}
if (leave_copy) {
- ig.Emit (OpCodes.Dup);
+ ec.ig.Emit (OpCodes.Dup);
if (IsRef) {
temp = new LocalTemporary (Type);
temp.Store (ec);
}
if (IsRef)
- StoreFromPtr (ig, type);
+ StoreFromPtr (ec.ig, type);
else
Variable.EmitAssign (ec);
/// Local variables
/// </summary>
public class LocalVariableReference : VariableReference {
- public readonly string Name;
+ readonly string name;
public Block Block;
public LocalInfo local_info;
bool is_readonly;
public LocalVariableReference (Block block, string name, Location l)
{
Block = block;
- Name = name;
+ this.name = name;
loc = l;
eclass = ExprClass.Variable;
}
}
//
- // A local Variable is always fixed.
+ // A local variable is always fixed
//
- public override bool IsFixed {
+ public override bool IsFixedVariable {
get { return true; }
}
get { return is_readonly; }
}
+ public override string Name {
+ get { return name; }
+ }
+
public bool VerifyAssigned (EmitContext ec)
{
VariableInfo variable_info = local_info.VariableInfo;
}
}
+ public override void SetHasAddressTaken ()
+ {
+ local_info.AddressTaken = true;
+ }
+
public override Expression CreateExpressionTree (EmitContext ec)
{
ArrayList arg = new ArrayList (1);
// flag it for capturing
//
if (ec.MustCaptureVariable (local_info)) {
- if (local_info.AddressTaken){
- AnonymousMethodBody.Error_AddressOfCapturedVar (local_info.Name, loc);
- return null;
- }
+ if (local_info.AddressTaken)
+ AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
- if (!ec.IsInProbingMode) {
+ if (ec.IsVariableCapturingRequired) {
AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec);
storey.CaptureLocalVariable (ec, local_info);
}
code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
} else if (right_side == EmptyExpression.LValueMemberOutAccess) {
code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
+ } else if (right_side == EmptyExpression.UnaryAddress) {
+ code = 459; msg = "Cannot take the address of {1} `{0}'";
} else {
code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
}
Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
- return null;
- }
-
- if (VariableInfo != null)
+ } else if (VariableInfo != null) {
VariableInfo.SetAssigned (ec);
+ }
return DoResolveBase (ec);
}
}
//
- // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
+ // A ref or out parameter is classified as a moveable variable, even
+ // if the argument given for the parameter is a fixed variable
//
- public override bool IsFixed {
- get { return pi.Parameter.ModFlags == Parameter.Modifier.NONE; }
+ public override bool IsFixedVariable {
+ get { return !IsRef; }
}
- public string Name {
+ public override string Name {
get { return Parameter.Name; }
}
Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
return false;
}
-
+
+ public override void SetHasAddressTaken ()
+ {
+ Parameter.HasAddressTaken = true;
+ }
+
void SetAssigned (EmitContext ec)
{
if (HasOutModifier && ec.DoFlowAnalysis)
bool DoResolveBase (EmitContext ec)
{
- Parameter par = Parameter;
- type = par.ParameterType;
+ type = pi.ParameterType;
eclass = ExprClass.Variable;
AnonymousExpression am = ec.CurrentAnonymousMethod;
if (IsRef) {
Report.Error (1628, loc,
"Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
- par.Name, am.ContainerType);
+ Name, am.ContainerType);
return false;
}
} else {
return true;
}
- // Don't capture parameters when the probing is on
- if (!ec.IsInProbingMode) {
+ if (ec.IsVariableCapturingRequired) {
+ if (pi.Parameter.HasAddressTaken)
+ AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
+
AnonymousMethodStorey storey = declared.CreateAnonymousMethodStorey (ec);
storey.CaptureParameter (ec, this);
}
} else
ig.Emit (OpCodes.Ldarg, x);
}
-
- public override string ToString ()
- {
- return "ParameterReference[" + Name + "]";
- }
}
/// <summary>
}
public Type Type {
- get {
- if (ArgType == AType.Ref || ArgType == AType.Out)
- return TypeManager.GetReferenceType (Expr.Type);
- else
- return Expr.Type;
- }
+ get { return Expr.Type; }
}
public Parameter.Modifier Modifier
if (Expr.eclass == ExprClass.MethodGroup)
return Expr.ExprClassName;
- return Expr.GetSignatureForError ();
+ return TypeManager.CSharpName (Expr.Type);
}
public bool ResolveMethodGroup (EmitContext ec)
return null;
}
- if (IsSpecialMethodInvocation (method)) {
- return null;
- }
+ IsSpecialMethodInvocation (method, loc);
if (mg.InstanceExpression != null)
mg.InstanceExpression.CheckMarshalByRefAccess (ec);
return mg.OverloadResolve (ec, ref Arguments, false, loc);
}
- bool IsSpecialMethodInvocation (MethodBase method)
+ public static bool IsSpecialMethodInvocation (MethodBase method, Location loc)
{
if (!TypeManager.IsSpecialMethod (method))
return false;
static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments)
{
- ParameterData pd = TypeManager.GetParameterData (mb);
-
- if (arguments == null)
- return new Type [0];
-
+ AParametersCollection pd = TypeManager.GetParameterData (mb);
+
Argument a = (Argument) arguments [pd.Count - 1];
Arglist list = (Arglist) a.Expr;
/// <summary>
/// This checks the ConditionalAttribute on the method
/// </summary>
- public static bool IsMethodExcluded (MethodBase method)
+ public static bool IsMethodExcluded (MethodBase method, Location loc)
{
if (method.IsConstructor)
return false;
return false;
}
- return AttributeTester.IsConditionalMethodExcluded (method);
+ return AttributeTester.IsConditionalMethodExcluded (method, loc);
}
/// <remarks>
}
}
- if (IsMethodExcluded (method))
+ if (IsMethodExcluded (method, loc))
return;
bool is_static = method.IsStatic;
}
}
+ //
+ // It's either a cast or delegate invocation
+ //
public class InvocationOrCast : ExpressionStatement
{
Expression expr;
}
public override Expression DoResolve (EmitContext ec)
+ {
+ Expression e = ResolveCore (ec);
+ if (e == null)
+ return null;
+
+ return e.Resolve (ec);
+ }
+
+ Expression ResolveCore (EmitContext ec)
{
//
// First try to resolve it as a cast.
//
- TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
- if ((te != null) && (te.eclass == ExprClass.Type)) {
- Cast cast = new Cast (te, argument, loc);
- return cast.Resolve (ec);
+ TypeExpr te = expr.ResolveAsBaseTerminal (ec, true);
+ if (te != null) {
+ return new Cast (te, argument, loc);
}
//
//
// Ok, so it's a Cast.
//
- if (expr.eclass == ExprClass.Type) {
- Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
- return cast.Resolve (ec);
+ if (expr.eclass == ExprClass.Type || expr.eclass == ExprClass.TypeParameter) {
+ return new Cast (expr, argument, loc);
}
+ if (expr.eclass == ExprClass.Namespace) {
+ expr.Error_UnexpectedKind (null, "type", loc);
+ return null;
+ }
+
//
// It's a delegate invocation.
//
return null;
}
- ArrayList args = new ArrayList ();
+ ArrayList args = new ArrayList (1);
args.Add (new Argument (argument, Argument.AType.Expression));
- DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
- return invocation.Resolve (ec);
+ return new DelegateInvocation (expr, args, loc);
}
public override ExpressionStatement ResolveStatement (EmitContext ec)
{
- //
- // First try to resolve it as a cast.
- //
- TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
- if ((te != null) && (te.eclass == ExprClass.Type)) {
- Error_InvalidExpressionStatement ();
+ Expression e = ResolveCore (ec);
+ if (e == null)
return null;
- }
- //
- // This can either be a type or a delegate invocation.
- // Let's just resolve it and see what we'll get.
- //
- expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
- if ((expr == null) || (expr.eclass == ExprClass.Type)) {
+ ExpressionStatement s = e as ExpressionStatement;
+ if (s == null) {
Error_InvalidExpressionStatement ();
return null;
}
- //
- // It's a delegate invocation.
- //
- if (!TypeManager.IsDelegateType (expr.Type)) {
- Error (149, "Method name expected");
- return null;
- }
-
- ArrayList args = new ArrayList ();
- args.Add (new Argument (argument, Argument.AType.Expression));
- DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
- return invocation.ResolveStatement (ec);
+ return s.ResolveStatement (ec);
}
public override void Emit (EmitContext ec)
// This class is used to "disable" the code generation for the
// temporary variable when initializing value types.
//
- class EmptyAddressOf : EmptyExpression, IMemoryLocation {
+ sealed class EmptyAddressOf : EmptyExpression, IMemoryLocation {
public void AddressOf (EmitContext ec, AddressOp Mode)
{
// nothing
}
-
- public bool IsFixed { get { return true; } }
}
/// <summary>
type = texpr.Type;
- if (type == TypeManager.void_type) {
- Error_VoidInvalidInTheContext (loc);
- return null;
- }
-
if (type.IsPointer) {
Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
TypeManager.CSharpName (type));
this.rank = rank;
loc = l;
- arguments = new ArrayList ();
+ arguments = new ArrayList (exprs.Count);
foreach (Expression e in exprs) {
arguments.Add (new Argument (e, Argument.AType.Expression));
Constant c = a.Expr as Constant;
if (c != null) {
- c = c.ImplicitConversionRequired (TypeManager.int32_type, a.Expr.Location);
+ c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Expr.Location);
}
if (c == null) {
args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
if (array_data != null) {
- foreach (Expression e in array_data)
+ for (int i = 0; i < array_data.Count; ++i) {
+ Expression e = (Expression) array_data [i];
+ if (e == null)
+ e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc);
+
args.Add (new Argument (e.CreateExpressionTree (ec)));
+ }
}
return CreateExpressionFactoryCall ("NewArrayInit", args);
Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
return false;
}
+
+ if (requested_base_type is VarExpr) {
+ Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer");
+ return false;
+ }
StringBuilder array_qualifier = new StringBuilder (rank);
if (!ResolveArrayType (ec))
return null;
- if ((array_element_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
- Report.Error (719, loc, "`{0}': array elements cannot be of static type",
- TypeManager.CSharpName (array_element_type));
- }
-
//
// First step is to validate the initializers and fill
// in any missing bits
foreach (Argument a in arguments)
a.Expr.MutateHoistedGenericType (storey);
}
-
- // TODO: finish !!
+
+ if (array_data != null) {
+ foreach (Expression e in array_data)
+ e.MutateHoistedGenericType (storey);
+ }
}
//
first_emit_temp.Release (ec);
}
- public override bool GetAttributableValue (Type value_type, out object value)
+ public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
{
if (arguments.Count != 1) {
// Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
- return base.GetAttributableValue (null, out value);
+ return base.GetAttributableValue (ec, null, out value);
}
if (array_data == null) {
return true;
}
// Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
- return base.GetAttributableValue (null, out value);
+ return base.GetAttributableValue (ec, null, out value);
}
Array ret = Array.CreateInstance (array_element_type, array_data.Count);
if (e == null)
continue;
- if (!e.GetAttributableValue (array_element_type, out element_value)) {
+ if (!e.GetAttributableValue (ec, array_element_type, out element_value)) {
value = null;
return false;
}
if (array_element_type == null || array_element_type == TypeManager.null_type ||
array_element_type == TypeManager.void_type || array_element_type == TypeManager.anonymous_method_type ||
arguments.Count != dimensions) {
- Report.Error (826, loc, "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
+ Error_NoBestType ();
return null;
}
return this;
}
+ void Error_NoBestType ()
+ {
+ Report.Error (826, loc,
+ "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
+ }
+
//
// Converts static initializer only
//
return element;
}
- element.Error_ValueCannotBeConverted (ec, element.Location, array_element_type, false);
- return element;
+ Error_NoBestType ();
+ return null;
}
}
public class This : VariableReference
{
- class ThisVariable : ILocalVariable
+ sealed class ThisVariable : ILocalVariable
{
public static readonly ILocalVariable Instance = new ThisVariable ();
get { return variable_info; }
}
- public override bool IsFixed {
+ public override bool IsFixedVariable {
get { return !TypeManager.IsValueType (type); }
}
}
}
+ public static bool IsThisAvailable (EmitContext ec)
+ {
+ if (ec.IsStatic || ec.IsInFieldInitializer)
+ return false;
+
+ if (ec.CurrentAnonymousMethod == null)
+ return true;
+
+ if (ec.TypeContainer is Struct && ec.CurrentIterator == null)
+ return false;
+
+ return true;
+ }
+
public bool ResolveBase (EmitContext ec)
{
+ if (eclass != ExprClass.Invalid)
+ return true;
+
eclass = ExprClass.Variable;
if (ec.TypeContainer.CurrentType != null)
else
type = ec.ContainerType;
- is_struct = ec.TypeContainer is Struct;
-
- if (ec.IsStatic) {
- Error (26, "Keyword `this' is not valid in a static property, " +
- "static method, or static field initializer");
- return false;
+ if (!IsThisAvailable (ec)) {
+ if (ec.IsStatic) {
+ Error (26, "Keyword `this' is not valid in a static property, static method, or static field initializer");
+ } else {
+ Report.Error (1673, loc,
+ "Anonymous methods inside structs cannot access instance members of `this'. " +
+ "Consider copying `this' to a local variable outside the anonymous method and using the local instead");
+ }
}
+ is_struct = ec.TypeContainer is Struct;
+
if (block != null) {
if (block.Toplevel.ThisVariable != null)
variable_info = block.Toplevel.ThisVariable.VariableInfo;
AnonymousExpression am = ec.CurrentAnonymousMethod;
if (am != null) {
- if (is_struct && !am.IsIterator) {
- Report.Error (1673, loc, "Anonymous methods inside structs " +
- "cannot access instance members of `this'. " +
- "Consider copying `this' to a local variable " +
- "outside the anonymous method and using the " +
- "local instead.");
- }
-
//
// this is hoisted to very top level block
//
- if (!ec.IsInProbingMode) {
+ if (ec.IsVariableCapturingRequired) {
// TODO: it could be optimized
AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec);
if (HoistedVariable == null) {
if (variable_info != null)
variable_info.SetAssigned (ec);
-
+
if (ec.TypeContainer is Class){
- Error (1604, "Cannot assign to 'this' because it is read-only");
- return null;
+ if (right_side == EmptyExpression.UnaryAddress)
+ Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
+ else if (right_side == EmptyExpression.OutAccess)
+ Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only");
+ else
+ Report.Error (1604, loc, "Cannot assign to `this' because it is read-only");
}
return this;
return block.GetHashCode ();
}
+ public override string Name {
+ get { return "this"; }
+ }
+
public override bool Equals (object obj)
{
This t = obj as This;
{
TopToplevelBlock.HoistedThisVariable = null;
}
+
+ public override void SetHasAddressTaken ()
+ {
+ // Nothing
+ }
}
/// <summary>
arg.Emit (ec);
}
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ foreach (Argument arg in Arguments)
+ arg.Expr.MutateHoistedGenericType (storey);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
Arglist target = (Arglist) t;
ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
}
- public override bool GetAttributableValue (Type value_type, out object value)
+ public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
{
if (TypeManager.ContainsGenericParameters (typearg) &&
!TypeManager.IsGenericTypeDefinition (typearg)) {
if (TypeManager.IsEnumType (type_queried))
type_queried = TypeManager.GetEnumUnderlyingType (type_queried);
- if (type_queried == TypeManager.void_type) {
- Expression.Error_VoidInvalidInTheContext (loc);
- return null;
- }
-
int size_of = GetTypeSize (type_queried);
if (size_of > 0) {
return new IntConstant (size_of, loc);
public class QualifiedAliasMember : MemberAccess
{
readonly string alias;
+ public static readonly string GlobalAlias = "global";
public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
: base (null, identifier, targs, l)
public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
- if (alias == "global") {
+ if (alias == GlobalAlias) {
expr = RootNamespace.Global;
return base.ResolveAsTypeStep (ec, silent);
}
if (Expr == null)
return null;
- if (Expr is Constant)
+ if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression)
return Expr;
eclass = Expr.eclass;
Expr.EmitBranchable (ec, target, on_true);
}
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ Expr.MutateHoistedGenericType (storey);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
CheckedExpr target = (CheckedExpr) t;
if (Expr == null)
return null;
- if (Expr is Constant)
+ if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression)
return Expr;
eclass = Expr.eclass;
Expr.EmitBranchable (ec, target, on_true);
}
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ Expr.MutateHoistedGenericType (storey);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
UnCheckedExpr target = (UnCheckedExpr) t;
public ElementAccess (Expression e, ArrayList e_list)
{
Expr = e;
-
loc = e.Location;
if (e_list == null)
return;
- Arguments = new ArrayList ();
+ Arguments = new ArrayList (e_list.Count);
foreach (Expression tmp in e_list)
Arguments.Add (new Argument (tmp, Argument.AType.Expression));
-
}
bool CommonResolve (EmitContext ec)
Expression MakePointerAccess (EmitContext ec, Type t)
{
- if (t == TypeManager.void_ptr_type){
- Error (242, "The array index operation is not valid on void pointers");
- return null;
- }
if (Arguments.Count != 1){
Error (196, "A pointer must be indexed by only one value");
return null;
}
}
- protected override int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
+ protected override int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters)
{
//
// Here is the trick, decrease number of arguments by 1 when only
Type current_type = ec.ContainerType;
Type base_type = current_type.BaseType;
- if (ec.IsStatic){
- Error (1511, "Keyword `base' is not available in a static method");
- return null;
- }
-
- if (ec.IsInFieldInitializer){
- Error (1512, "Keyword `base' is not available in the current context");
+ if (!This.IsThisAvailable (ec)) {
+ if (ec.IsStatic) {
+ Error (1511, "Keyword `base' is not available in a static method");
+ } else {
+ Error (1512, "Keyword `base' is not available in the current context");
+ }
return null;
}
/// is needed (the `New' class).
/// </summary>
public class EmptyExpression : Expression {
- public static readonly EmptyExpression Null = new EmptyExpression ();
+ public static readonly Expression Null = new EmptyExpression ();
public static readonly EmptyExpression OutAccess = new EmptyExpression ();
public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression ();
public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression ();
+ public static readonly EmptyExpression UnaryAddress = new EmptyExpression ();
static EmptyExpression temp = new EmptyExpression ();
public static EmptyExpression Grab ()
source.Emit (ec);
ec.ig.Emit (OpCodes.Call, method);
}
+
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ source.MutateHoistedGenericType (storey);
+ method = storey.MutateGenericMethod (method);
+ }
}
// <summary>
loc = l;
}
- public Expression RemoveNullable ()
- {
- if (dim.EndsWith ("?")) {
- dim = dim.Substring (0, dim.Length - 1);
- if (dim.Length == 0)
- return left;
- }
-
- return this;
- }
-
protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
{
TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false);
return null;
Type ltype = lexpr.Type;
- if ((ltype == TypeManager.void_type) && (dim != "*")) {
- Error_VoidInvalidInTheContext (loc);
- return null;
- }
-
#if GMCS_SOURCE
if ((dim.Length > 0) && (dim [0] == '?')) {
TypeExpr nullable = new Nullable.NullableType (left, loc);
if (dim == "*" && !TypeManager.VerifyUnManaged (ltype, loc))
return null;
- if (dim != "" && dim [0] == '[' &&
- (ltype == TypeManager.arg_iterator_type || ltype == TypeManager.typed_reference_type)) {
- Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
- return null;
+ if (dim.Length != 0 && dim [0] == '[') {
+ if (TypeManager.IsSpecialType (ltype)) {
+ Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
+ return null;
+ }
+
+ if ((ltype.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+ Report.SymbolRelatedToPreviousError (ltype);
+ Report.Error (719, loc, "Array elements cannot be of static type `{0}'",
+ TypeManager.CSharpName (ltype));
+ }
}
if (dim != "")
if (type.IsPointer && !ec.IsInUnsafeScope){
UnsafeError (loc);
- return null;
}
eclass = ExprClass.Type;
// for known types like List<T>, Dictionary<T, U>
for (int i = 0; i < Arguments.Count; ++i) {
- Expression expr = ((Expression) Arguments [i]).Resolve (ec);
+ Expression expr = Arguments [i] as Expression;
+ if (expr == null)
+ return null;
+
+ expr = expr.Resolve (ec);
if (expr == null)
return null;
if (e == null)
return null;
+ if (e.eclass == ExprClass.MethodGroup) {
+ Error_InvalidInitializer (e.ExprClassName);
+ return null;
+ }
+
type = e.Type;
if (type == TypeManager.void_type || type == TypeManager.null_type ||
type == TypeManager.anonymous_method_type || type.IsPointer) {
- Error_InvalidInitializer (e);
+ Error_InvalidInitializer (e.GetSignatureForError ());
return null;
}
return e;
}
- protected virtual void Error_InvalidInitializer (Expression initializer)
+ protected virtual void Error_InvalidInitializer (string initializer)
{
Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
- Name, initializer.GetSignatureForError ());
+ Name, initializer);
}
public override void Emit (EmitContext ec)