void AddressOf (EmitContext ec, AddressOp mode);
}
- /// <summary>
- /// This interface is implemented by variables
- /// </summary>
+ // TODO: Rename to something meaningful, this is flow-analysis interface only
public interface IVariable {
- VariableInfo VariableInfo {
- get;
- }
-
- bool VerifyFixed ();
+ VariableInfo VariableInfo { get; }
+ bool IsFixed { get; }
}
/// <remarks>
return;
}
- if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) {
- Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
- ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target));
- return;
- }
-
Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
TypeManager.CSharpName (type),
TypeManager.CSharpName (target));
throw new NotImplementedException ();
}
+ protected void Error_PointerInsideExpressionTree ()
+ {
+ Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
+ }
+
/// <summary>
/// Returns an expression that can be used to invoke operator true
/// on the expression if it exists.
static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
{
MethodGroupExpr operator_group;
- operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
+ string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
+ operator_group = MethodLookup (ec.ContainerType, e.Type, mname, loc) as MethodGroupExpr;
if (operator_group == null)
return null;
return cloned;
}
- public virtual Expression CreateExpressionTree (EmitContext ec)
- {
- throw new NotImplementedException (
- "Expression tree conversion not implemented for " + GetType ());
- }
+ //
+ // Implementation of expression to expression tree conversion
+ //
+ public abstract Expression CreateExpressionTree (EmitContext ec);
protected Expression CreateExpressionFactoryCall (string name, ArrayList args)
{
ArrayList args = new ArrayList (2);
args.Add (new Argument (child.CreateExpressionTree (ec)));
args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+
+ if (type.IsPointer || child.Type.IsPointer)
+ Error_PointerInsideExpressionTree ();
+
return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args);
}
}
public override bool IsNull {
- get {
- return child.IsNull;
- }
+ get { return child.IsNull; }
}
}
public class EmptyCast : TypeCast {
- bool is_implicit;
-
EmptyCast (Expression child, Type target_type)
: base (child, target_type)
{
}
- //
- // HACK: This is just temporary hack before real EmptyCast clean-up required by expression trees
- //
- public static Expression Create (Expression child, Type type, bool is_implicit)
- {
- EmptyCast e = new EmptyCast (child, type);
- e.is_implicit = true;
- return e;
- }
-
public static Expression Create (Expression child, Type type)
{
Constant c = child as Constant;
if (c != null)
return new EmptyConstantCast (c, type);
- return new EmptyCast (child, type);
- }
+ EmptyCast e = child as EmptyCast;
+ if (e != null)
+ return new EmptyCast (e.child, type);
- public override Expression CreateExpressionTree (EmitContext ec)
- {
- if (is_implicit)
- return child.CreateExpressionTree (ec);
- else
- return base.CreateExpressionTree (ec);
+ return new EmptyCast (child, type);
}
public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
{
child.EmitSideEffect (ec);
}
-
}
/// <summary>
ArrayList args = new ArrayList (2);
args.Add (new Argument (child.CreateExpressionTree (ec)));
args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+ if (type.IsPointer)
+ Error_PointerInsideExpressionTree ();
+
return CreateExpressionFactoryCall ("Convert", args);
}
/// section 10.8.1 (Fully Qualified Names).
/// </summary>
public abstract class FullNamedExpression : Expression {
+
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ throw new NotSupportedException ("ET");
+ }
+
public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
return this;
loc = l;
}
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ // Nothing to clone
+ }
+
protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
{
Expression expr;
"with an instance reference, qualify it with a type name instead", name);
}
+ public static void Error_BaseAccessInExpressionTree (Location loc)
+ {
+ Report.Error (831, loc, "An expression tree may not contain a base access");
+ }
+
// TODO: possible optimalization
// Cache resolved constant result in FieldBuilder <-> expression map
public virtual MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
//
if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) {
p = TypeManager.GetTypeArguments (p) [0];
+ }
+ if (TypeManager.DropGenericTypeArguments (q) == TypeManager.expression_type) {
q = TypeManager.GetTypeArguments (q) [0];
}
+
p = Delegate.GetInvokeMethod (null, p).ReturnType;
q = Delegate.GetInvokeMethod (null, q).ReturnType;
} else {
public override Expression CreateExpressionTree (EmitContext ec)
{
+ if (best_candidate == null) {
+ Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
+ return null;
+ }
+
if (best_candidate.IsConstructor)
return new TypeOfConstructorInfo (best_candidate, loc);
+
+ IMethodData md = TypeManager.GetMethod (best_candidate);
+ if (md != null && md.IsExcluded ())
+ Report.Error (765, loc,
+ "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
return new TypeOfMethodInfo (best_candidate, loc);
}
return 0;
}
- // FIXME: Kill this abomination (EmitContext.TempEc)
- EmitContext prevec = EmitContext.TempEc;
- EmitContext.TempEc = ec;
- try {
- if (delegate_type != null ?
- !Delegate.IsTypeCovariant (argument.Expr, parameter) :
- !Convert.ImplicitConversionExists (ec, argument.Expr, parameter))
- return 2;
-
- if (arg_mod != param_mod)
- return 1;
+ if (delegate_type != null ?
+ !Delegate.IsTypeCovariant (argument.Expr, parameter) :
+ !Convert.ImplicitConversionExists (ec, argument.Expr, parameter))
+ return 2;
- } finally {
- EmitContext.TempEc = prevec;
- }
+ if (arg_mod != param_mod)
+ return 1;
return 0;
}
continue;
}
-
+
Expression conv;
if (TypeManager.IsEqual (a.Type, pt)) {
conv = a.Expr;
// Convert params arguments to an array initializer
//
if (params_initializers != null) {
- params_initializers.Add (conv);
+ // we choose to use 'a.Expr' rather than 'conv' so that
+ // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
+ params_initializers.Add (a.Expr);
arguments.RemoveAt (a_idx--);
--arg_count;
continue;
}
-
+
// Update the argument with the implicit conversion
a.Expr = conv;
}
public override Expression CreateExpressionTree (EmitContext ec)
{
- throw new NotSupportedException ();
+ throw new NotSupportedException ("ET");
}
public override Expression DoResolve (EmitContext ec)
// If the instance expression is a local variable or parameter.
IVariable var = InstanceExpression as IVariable;
- if ((var == null) || (var.VariableInfo == null))
+ if (var == null || var.VariableInfo == null)
return this;
VariableInfo vi = var.VariableInfo;
override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
IVariable var = InstanceExpression as IVariable;
- if ((var != null) && (var.VariableInfo != null))
+ if (var != null && var.VariableInfo != null)
var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
}
}
- public bool VerifyFixed ()
- {
- IVariable variable = InstanceExpression as IVariable;
- // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
- // We defer the InstanceExpression check after the variable check to avoid a
- // separate null check on InstanceExpression.
- return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
- }
-
public override int GetHashCode ()
{
return FieldInfo.GetHashCode ();
}
+
+ public bool IsFixed {
+ get {
+ IVariable variable = InstanceExpression as IVariable;
+ // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
+ // We defer the InstanceExpression check after the variable check to avoid a
+ // separate null check on InstanceExpression.
+ return variable != null && InstanceExpression.Type.IsValueType && variable.IsFixed;
+ }
+ }
public override bool Equals (object obj)
{
return;
}
- //
- // String concatenation creates a new string instance
- //
- prepared = prepare_for_load && !(source is StringConcat);
+ prepared = prepare_for_load;
EmitInstance (ec, prepared);
source.Emit (ec);
public override Expression CreateExpressionTree (EmitContext ec)
{
+ ArrayList args;
if (IsSingleDimensionalArrayLength ()) {
- ArrayList args = new ArrayList (1);
+ args = new ArrayList (1);
args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
return CreateExpressionFactoryCall ("ArrayLength", args);
}
- // TODO: it's waiting for PropertyExpr refactoring
- //ArrayList args = new ArrayList (2);
- //args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
- //args.Add (getter expression);
- //return CreateExpressionFactoryCall ("Property", args);
- return base.CreateExpressionTree (ec);
+ if (is_base) {
+ Error_BaseAccessInExpressionTree (loc);
+ return null;
+ }
+
+ args = new ArrayList (2);
+ if (InstanceExpression == null)
+ args.Add (new Argument (new NullLiteral (loc)));
+ else
+ args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+ args.Add (new Argument (new TypeOfMethodInfo (getter, loc)));
+ return CreateExpressionFactoryCall ("Property", args);
}
public Expression CreateSetterTypeOfExpression ()
string t_name = InstanceExpression.Type.Name;
int t_name_len = t_name.Length;
- return t_name_len > 2 && t_name [t_name_len - 2] == '[' && t_name [t_name_len - 3] != ']';
+ return t_name_len > 2 && t_name [t_name_len - 2] == '[';
}
override public Expression DoResolve (EmitContext ec)
Expression my_source = source;
if (prepare_for_load) {
- if (source is StringConcat)
- EmitInstance (ec, false);
- else
- prepared = true;
-
+ prepared = true;
source.Emit (ec);
- prepared = true;
if (leave_copy) {
ec.ig.Emit (OpCodes.Dup);
if (!is_static) {
return base.ResolveMemberAccess (ec, left, loc, original);
}
-
bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
{
if (is_static) {
public override Expression CreateExpressionTree (EmitContext ec)
{
- throw new NotSupportedException ();
+ throw new NotSupportedException ("ET");
}
public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
- return DoResolve (ec);
+ // contexts where an LValue is valid have already devolved to FieldExprs
+ Error_CannotAssign ();
+ return null;
}
public override Expression DoResolve (EmitContext ec)
if (!InstanceResolve (ec, must_do_cs1540_check))
return null;
+
+ if (!ec.IsInCompoundAssignment) {
+ Error_CannotAssign ();
+ return null;
+ }
return this;
}
public override void Emit (EmitContext ec)
{
- Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
- "(except on the defining type)", GetSignatureForError ());
+ Error_CannotAssign ();
+ }
+
+ public void Error_CannotAssign ()
+ {
+ Report.Error (70, loc,
+ "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
+ GetSignatureForError (), TypeManager.CSharpName (EventInfo.DeclaringType));
}
public override string GetSignatureForError ()
return TypeManager.CSharpSignature (EventInfo);
}
- public void EmitAddOrRemove (EmitContext ec, Expression source)
+ public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
{
- BinaryDelegate source_del = source as BinaryDelegate;
- if (source_del == null) {
- Emit (ec);
- return;
- }
- Expression handler = source_del.Right;
-
- Argument arg = new Argument (handler, Argument.AType.Expression);
- ArrayList args = new ArrayList ();
-
- args.Add (arg);
-
- if (source_del.IsAddition)
- Invocation.EmitCall (
- ec, IsBase, InstanceExpression, add_accessor, args, loc);
- else
- Invocation.EmitCall (
- ec, IsBase, InstanceExpression, remove_accessor, args, loc);
+ ArrayList args = new ArrayList (1);
+ args.Add (new Argument (source, Argument.AType.Expression));
+ Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc);
}
}
- public class TemporaryVariable : Expression, IMemoryLocation
+ public class TemporaryVariable : VariableReference
{
LocalInfo li;
Variable var;
-
+
public TemporaryVariable (Type type, Location loc)
{
this.type = type;
this.loc = loc;
- eclass = ExprClass.Value;
+ eclass = ExprClass.Variable;
}
-
+
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ throw new NotSupportedException ("ET");
+ }
+
public override Expression DoResolve (EmitContext ec)
{
if (li != null)
return this;
-
+
TypeExpr te = new TypeExpression (type, loc);
li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
if (!li.Resolve (ec))
var = scope.AddLocal (li);
type = var.Type;
}
-
+
return this;
}
- public Variable Variable {
- get { return var != null ? var : li.Variable; }
- }
-
public override void Emit (EmitContext ec)
{
- Variable.EmitInstance (ec);
- Variable.Emit (ec);
+ Emit (ec, false);
}
-
- public void EmitLoadAddress (EmitContext ec)
+
+ public void EmitAssign (EmitContext ec, Expression source)
{
- Variable.EmitInstance (ec);
- Variable.EmitAddressOf (ec);
+ EmitAssign (ec, source, false, false);
}
-
- public void Store (EmitContext ec, Expression right_side)
- {
- Variable.EmitInstance (ec);
- right_side.Emit (ec);
- Variable.EmitAssign (ec);
+
+ public override bool IsFixed {
+ get { return true; }
}
-
- public void EmitThis (EmitContext ec)
- {
- Variable.EmitInstance (ec);
+
+ public override bool IsRef {
+ get { return false; }
}
-
- public void EmitStore (EmitContext ec)
- {
- Variable.EmitAssign (ec);
+
+ public override Variable Variable {
+ get { return var != null ? var : li.Variable; }
}
-
- public void AddressOf (EmitContext ec, AddressOp mode)
- {
- EmitLoadAddress (ec);
+
+ public override VariableInfo VariableInfo {
+ get { throw new NotImplementedException (); }
}
}
}
}
- public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ public bool InferType (EmitContext ec, Expression right_side)
{
if (type != null)
throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
if (type == TypeManager.null_type || type == TypeManager.void_type || type == TypeManager.anonymous_method_type) {
Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
right_side.GetSignatureForError ());
- return null;
+ return false;
}
eclass = ExprClass.Variable;
- return this;
+ return true;
}
protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec)