return Expr;
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return Expr.DoResolveLValue (ec, right_side);
+ }
+
public override void Emit (EmitContext ec)
{
throw new Exception ("Should not happen");
public Expression Expr;
Expression enum_conversion;
- public Unary (Operator op, Expression expr, Location loc)
+ public Unary (Operator op, Expression expr)
{
Oper = op;
Expr = expr;
- this.loc = loc;
+ loc = expr.Location;
}
// <summary>
if (expr_type == TypeManager.float_type) {
FloatLiteral fl = e as FloatLiteral;
// For better error reporting
- if (fl != null) {
- fl.Value = -fl.Value;
- return fl;
- }
+ if (fl != null)
+ return new FloatLiteral (-fl.Value, e.Location);
+
return new FloatConstant (-((FloatConstant)e).Value, e.Location);
}
if (expr_type == TypeManager.double_type) {
DoubleLiteral dl = e as DoubleLiteral;
// For better error reporting
- if (dl != null) {
- dl.Value = -dl.Value;
- return dl;
- }
-
+ if (dl != null)
+ return new DoubleLiteral (-dl.Value, e.Location);
+
return new DoubleConstant (-((DoubleConstant)e).Value, e.Location);
}
if (expr_type == TypeManager.decimal_type)
return null;
if (TypeManager.IsNullableValueType (Expr.Type))
- return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
+ return new Nullable.LiftedUnaryOperator (Oper, Expr).Resolve (ec);
//
// Attempt to use a constant folding operation.
//
UserOperatorCall method;
- public UnaryMutator (Mode m, Expression e, Location l)
+ public UnaryMutator (Mode m, Expression e)
{
mode = m;
- loc = l;
+ loc = e.Location;
expr = e;
}
Expression ResolveOperator (EmitContext ec)
{
type = expr.Type;
+
+ //
+ // The operand of the prefix/postfix increment decrement operators
+ // should be an expression that is classified as a variable,
+ // a property access or an indexer access
+ //
+ 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");
+ }
//
// Step 1: Perform Operator Overload location
return null;
}
- //
- // The operand of the prefix/postfix increment decrement operators
- // should be an expression that is classified as a variable,
- // a property access or an indexer access
- //
- 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 this;
}
t_is_nullable = true;
}
- if (t.IsValueType) {
+ if (TypeManager.IsStruct (t)) {
if (d == t) {
//
// D and T are the same value types but D can be null
if (TypeManager.IsGenericParameter (t))
return ResolveGenericParameter (d, t);
- if (d.IsValueType) {
+ if (TypeManager.IsStruct (d)) {
bool temp;
if (Convert.ImplicitBoxingConversionExists (expr, t, out temp))
return CreateConstantResult (true);
#if GMCS_SOURCE
GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
if (constraints != null) {
- if (constraints.IsReferenceType && d.IsValueType)
+ if (constraints.IsReferenceType && TypeManager.IsStruct (d))
return CreateConstantResult (false);
- if (constraints.IsValueType && !d.IsValueType)
+ if (constraints.IsValueType && !TypeManager.IsStruct (d))
return CreateConstantResult (TypeManager.IsEqual (d, t));
}
expr.Emit (ec);
if (do_isinst)
- ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+ ig.Emit (OpCodes.Isinst, type);
#if GMCS_SOURCE
- if (TypeManager.IsNullableType (type))
+ if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type))
ig.Emit (OpCodes.Unbox_Any, type);
#endif
}
public override Expression DoResolve (EmitContext ec)
{
+ // Because expr is modified
+ if (eclass != ExprClass.Invalid)
+ return this;
+
if (resolved_type == null) {
resolved_type = base.DoResolve (ec);
if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) {
if (probe_type_expr is TypeParameterExpr) {
Report.Error (413, loc,
- "The `as' operator cannot be used with a non-reference type parameter `{0}'",
+ "The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint",
probe_type_expr.GetSignatureForError ());
} else {
Report.Error (77, loc,
protected override string OperatorName {
get { return "as"; }
}
+
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+ {
+ type = storey.MutateType (type);
+ base.MutateHoistedGenericType (storey);
+ }
public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
{
// The conversion rules are ignored in enum context but why
if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
- left = lc = EnumLiftUp (ec, lc, rc, loc);
- if (lc == null)
- return null;
-
- right = rc = EnumLiftUp (ec, rc, lc, loc);
- if (rc == null)
- return null;
+ lc = EnumLiftUp (ec, lc, rc, loc);
+ if (lc != null)
+ rc = EnumLiftUp (ec, rc, lc, loc);
}
if (rc != null && lc != null) {
}
if (RootContext.Version >= LanguageVersion.ISO_2 &&
- (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type) ||
- (left is NullLiteral && right.Type.IsValueType) || (right is NullLiteral && left.Type.IsValueType)))
+ ((TypeManager.IsNullableType (left.Type) && (right is NullLiteral || TypeManager.IsNullableType (right.Type) || TypeManager.IsValueType (right.Type))) ||
+ (TypeManager.IsValueType (left.Type) && right is NullLiteral) ||
+ (TypeManager.IsNullableType (right.Type) && (left is NullLiteral || TypeManager.IsNullableType (left.Type) || TypeManager.IsValueType (left.Type))) ||
+ (TypeManager.IsValueType (right.Type) && left is NullLiteral)))
return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
return DoResolveCore (ec, left, right);
return null;
} else if (l.IsInterface) {
l = TypeManager.object_type;
- } else if (l.IsValueType) {
+ } else if (TypeManager.IsStruct (l)) {
return null;
}
return null;
} else if (r.IsInterface) {
r = TypeManager.object_type;
- } else if (r.IsValueType) {
+ } else if (TypeManager.IsStruct (r)) {
return null;
}
LocalTemporary temp;
#region Abstract
- public abstract HoistedVariable HoistedVariable { get; }
+ public abstract HoistedVariable GetHoistedVariable (EmitContext ec);
public abstract bool IsFixed { get; }
public abstract bool IsRef { get; }
public abstract string Name { get; }
public void AddressOf (EmitContext ec, AddressOp mode)
{
- if (IsHoistedEmitRequired (ec)) {
- HoistedVariable.AddressOf (ec, mode);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null) {
+ hv.AddressOf (ec, mode);
return;
}
{
Report.Debug (64, "VARIABLE EMIT", this, Variable, type, IsRef, loc);
- if (IsHoistedEmitRequired (ec)) {
- HoistedVariable.Emit (ec, leave_copy);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null) {
+ hv.Emit (ec, leave_copy);
return;
}
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
bool prepare_for_load)
{
- Report.Debug (64, "VARIABLE EMIT ASSIGN", this, Variable, type, IsRef,
- source, loc);
-
- if (IsHoistedEmitRequired (ec)) {
- HoistedVariable.EmitAssign (ec, source, leave_copy, prepare_for_load);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null) {
+ hv.EmitAssign (ec, source, leave_copy, prepare_for_load);
return;
}
- if (IsRef)
- Variable.Emit (ec);
-
- source.Emit (ec);
-
- // HACK: variable is already emitted when source is an initializer
- if (source is NewInitialize) {
- if (leave_copy) {
- Variable.Emit (ec);
+ New n_source = source as New;
+ if (n_source != null) {
+ if (!n_source.Emit (ec, this)) {
+ if (leave_copy)
+ EmitLoad (ec);
+ return;
}
- return;
+ } else {
+ if (IsRef)
+ EmitLoad (ec);
+
+ source.Emit (ec);
}
if (leave_copy) {
}
public bool IsHoisted {
- get { return HoistedVariable != null; }
- }
-
- protected virtual bool IsHoistedEmitRequired (EmitContext ec)
- {
- //
- // Default implementation return true when there is a hosted variable
- //
- return HoistedVariable != null;
+ get { return GetHoistedVariable (null) != null; }
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
get { return local_info.VariableInfo; }
}
- public override HoistedVariable HoistedVariable {
- get { return local_info.HoistedVariableReference; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return local_info.HoistedVariableReference;
}
//
/// </summary>
public class ParameterReference : VariableReference {
readonly ToplevelParameterInfo pi;
- readonly ToplevelBlock referenced;
- public ParameterReference (ToplevelBlock referenced, ToplevelParameterInfo pi, Location loc)
+ public ParameterReference (ToplevelParameterInfo pi, Location loc)
{
this.pi = pi;
- this.referenced = referenced;
this.loc = loc;
}
get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; }
}
- public override HoistedVariable HoistedVariable {
- get { return pi.Parameter.HoistedVariableReference; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return pi.Parameter.HoistedVariableReference;
}
//
if (am == null)
return true;
- ToplevelBlock declared = pi.Block;
- if (declared != referenced) {
- if (IsRef) {
- Report.Error (1628, loc,
- "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
- Name, am.ContainerType);
- return false;
+ Block b = ec.CurrentBlock;
+ while (b != null) {
+ IParameterData[] p = b.Toplevel.Parameters.FixedParameters;
+ for (int i = 0; i < p.Length; ++i) {
+ if (p [i] != Parameter)
+ continue;
+
+ //
+ // Skip closest anonymous method parameters
+ //
+ if (b == ec.CurrentBlock && !am.IsIterator)
+ return true;
+
+ if (IsRef) {
+ Report.Error (1628, loc,
+ "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
+ Name, am.ContainerType);
+ }
+
+ b = null;
+ break;
}
- } else {
- if (!am.IsIterator)
- return true;
+
+ if (b != null)
+ b = b.Toplevel.Parent;
}
- if (ec.IsVariableCapturingRequired) {
- if (pi.Parameter.HasAddressTaken)
- AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
+ if (pi.Parameter.HasAddressTaken)
+ AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
- AnonymousMethodStorey storey = declared.CreateAnonymousMethodStorey (ec);
+ if (ec.IsVariableCapturingRequired) {
+ AnonymousMethodStorey storey = pi.Block.CreateAnonymousMethodStorey (ec);
storey.CaptureParameter (ec, this);
}
if (pr == null)
return false;
- return Name == pr.Name && referenced == pr.referenced;
+ return Name == pr.Name;
}
protected override void CloneTo (CloneContext clonectx, Expression target)
public override Expression CreateExpressionTree (EmitContext ec)
{
- if (IsHoistedEmitRequired (ec))
- return HoistedVariable.CreateExpressionTree (ec);
+ HoistedVariable hv = GetHoistedVariable (ec);
+ if (hv != null)
+ return hv.CreateExpressionTree (ec);
return Parameter.ExpressionTreeVariableReference ();
}
return null;
}
- if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == "Finalize") {
+ if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == Destructor.MetadataName) {
if (mg.IsBase)
Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
else
bool is_static = method.IsStatic;
if (!is_static){
this_call = instance_expr is This;
- if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType))
+ if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type) || (!this_call && TypeManager.IsStruct (instance_expr.Type)))
struct_call = true;
//
//
// Push the instance expression
//
- if (TypeManager.IsValueType (iexpr_type)) {
+ if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) {
//
// Special case: calls to a function declared in a
// reference-type with a value-type argument need
// to have their value boxed.
- if (decl_type.IsValueType ||
+ if (TypeManager.IsStruct (decl_type) ||
TypeManager.IsGenericParameter (iexpr_type)) {
//
// If the expression implements IMemoryLocation, then
if (!omit_args)
EmitArguments (ec, Arguments, dup_args, this_arg);
-#if GMCS_SOURCE
- if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
- ig.Emit (OpCodes.Constrained, instance_expr.Type);
-#endif
-
OpCode call_op;
- if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
+ if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) {
call_op = OpCodes.Call;
- else
+ } else {
call_op = OpCodes.Callvirt;
+
+#if GMCS_SOURCE
+ if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
+ ig.Emit (OpCodes.Constrained, instance_expr.Type);
+#endif
+ }
if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
Type[] varargs_types = GetVarargsTypes (method, Arguments);
}
}
}
-
+/*
//
// It's either a cast or delegate invocation
//
target.argument = argument.Clone (clonectx);
}
}
+*/
- //
- // This class is used to "disable" the code generation for the
- // temporary variable when initializing value types.
- //
- sealed class EmptyAddressOf : EmptyExpression, IMemoryLocation {
- public void AddressOf (EmitContext ec, AddressOp Mode)
- {
- // nothing
- }
- }
-
/// <summary>
/// Implements the new expression
/// </summary>
// but if `type' is not null, it *might* contain a NewDelegate
// (because of field multi-initialization)
//
- public Expression RequestedType;
+ Expression RequestedType;
MethodGroupExpr method;
- //
- // If set, the new expression is for a value_target, and
- // we will not leave anything on the stack.
- //
- protected Expression value_target;
- protected bool value_target_set;
- bool is_type_parameter = false;
+ bool is_type_parameter;
public New (Expression requested_type, ArrayList arguments, Location l)
{
loc = l;
}
- public bool SetTargetVariable (Expression value)
- {
- value_target = value;
- value_target_set = true;
- if (!(value_target is IMemoryLocation)){
- Error_UnexpectedKind (null, "variable", loc);
- return false;
- }
- return true;
- }
-
- //
- // This function is used to disable the following code sequence for
- // value type initialization:
- //
- // AddressOf (temporary)
- // Construct/Init
- // LoadTemporary
- //
- // Instead the provide will have provided us with the address on the
- // stack to store the results.
- //
- static Expression MyEmptyExpression;
-
- public void DisableTemporaryValueType ()
- {
- if (MyEmptyExpression == null)
- MyEmptyExpression = new EmptyAddressOf ();
-
- //
- // To enable this, look into:
- // test-34 and test-89 and self bootstrapping.
- //
- // For instance, we can avoid a copy by using `newobj'
- // instead of Call + Push-temp on value types.
-// value_target = MyEmptyExpression;
- }
-
-
/// <summary>
/// Converts complex core type syntax like 'new int ()' to simple constant
/// </summary>
return null;
}
- bool is_struct = type.IsValueType;
+ bool is_struct = TypeManager.IsStruct (type);
eclass = ExprClass.Value;
//
}
//
- // This DoEmit can be invoked in two contexts:
+ // This Emit can be invoked in two contexts:
// * As a mechanism that will leave a value on the stack (new object)
// * As one that wont (init struct)
//
- // You can control whether a value is required on the stack by passing
- // need_value_on_stack. The code *might* leave a value on the stack
- // so it must be popped manually
- //
// If we are dealing with a ValueType, we have a few
// situations to deal with:
//
//
// Returns whether a value is left on the stack
//
- bool DoEmit (EmitContext ec, bool need_value_on_stack)
+ // *** Implementation note ***
+ //
+ // To benefit from this optimization, each assignable expression
+ // has to manually cast to New and call this Emit.
+ //
+ // TODO: It's worth to implement it for arrays and fields
+ //
+ public virtual bool Emit (EmitContext ec, IMemoryLocation target)
{
+ if (is_type_parameter)
+ return DoEmitTypeParameter (ec);
+
bool is_value_type = TypeManager.IsValueType (type);
ILGenerator ig = ec.ig;
+ VariableReference vr = target as VariableReference;
- if (is_value_type){
- IMemoryLocation ml;
-
- // Allow DoEmit() to be called multiple times.
- // We need to create a new LocalTemporary each time since
- // you can't share LocalBuilders among ILGeneators.
- if (!value_target_set)
- value_target = new LocalTemporary (type);
-
- ml = (IMemoryLocation) value_target;
- ml.AddressOf (ec, AddressOp.Store);
+ if (target != null && is_value_type && (vr != null || method == null)) {
+ target.AddressOf (ec, AddressOp.Store);
+ } else if (vr != null && vr.IsRef) {
+ vr.EmitLoad (ec);
}
if (method != null)
method.EmitArguments (ec, Arguments);
- if (is_value_type){
- if (method == null)
+ if (is_value_type) {
+ if (method == null) {
ig.Emit (OpCodes.Initobj, type);
- else
+ return false;
+ }
+
+ if (vr != null) {
ig.Emit (OpCodes.Call, (ConstructorInfo) method);
- if (need_value_on_stack){
- value_target.Emit (ec);
- return true;
- }
- return false;
- } else {
- ConstructorInfo ci = (ConstructorInfo) method;
+ return false;
+ }
+ }
+
+ ConstructorInfo ci = (ConstructorInfo) method;
#if MS_COMPATIBLE
- if (TypeManager.IsGenericType (type))
- ci = TypeBuilder.GetConstructor (type, ci);
+ if (TypeManager.IsGenericType (type))
+ ci = TypeBuilder.GetConstructor (type, ci);
#endif
- ig.Emit (OpCodes.Newobj, ci);
- return true;
- }
+
+ ig.Emit (OpCodes.Newobj, ci);
+ return true;
}
public override void Emit (EmitContext ec)
{
- if (is_type_parameter)
- DoEmitTypeParameter (ec);
- else
- DoEmit (ec, true);
+ LocalTemporary v = null;
+ if (method == null && TypeManager.IsValueType (type)) {
+ // TODO: Use temporary variable from pool
+ v = new LocalTemporary (type);
+ }
+
+ if (!Emit (ec, v))
+ v.Emit (ec);
}
public override void EmitStatement (EmitContext ec)
{
- bool value_on_stack;
-
- if (is_type_parameter)
- value_on_stack = DoEmitTypeParameter (ec);
- else
- value_on_stack = DoEmit (ec, false);
+ LocalTemporary v = null;
+ if (method == null && TypeManager.IsValueType (type)) {
+ // TODO: Use temporary variable from pool
+ v = new LocalTemporary (type);
+ }
- if (value_on_stack)
+ if (Emit (ec, v))
ec.ig.Emit (OpCodes.Pop);
-
}
public virtual bool HasInitializer {
return;
}
- if (!type.IsValueType){
+ if (!TypeManager.IsStruct (type)){
//
// We throw an exception. So far, I believe we only need to support
// value types:
throw new Exception ("AddressOf should not be used for classes");
}
- if (!value_target_set)
- value_target = new LocalTemporary (type);
+ LocalTemporary value_target = new LocalTemporary (type);
IMemoryLocation ml = (IMemoryLocation) value_target;
ml.AddressOf (ec, AddressOp.Store);
expect_initializers = true;
}
- void Error_IncorrectArrayInitializer ()
+ public static void Error_IncorrectArrayInitializer (Location loc)
{
- Error (178, "Invalid rank specifier: expected `,' or `]'");
+ Report.Error (178, loc, "Invalid rank specifier: expected `,' or `]'");
}
protected override void Error_NegativeArrayIndex (Location loc)
int value = (int) c.GetValue ();
if (value != probe.Count) {
- Error_IncorrectArrayInitializer ();
+ Error_IncorrectArrayInitializer (loc);
return false;
}
child_bounds = current_bounds;
else if (child_bounds != current_bounds){
- Error_IncorrectArrayInitializer ();
+ Error_IncorrectArrayInitializer (loc);
return false;
}
if (idx + 1 >= dimensions){
return false;
} else {
if (child_bounds != -1){
- Error_IncorrectArrayInitializer ();
+ Error_IncorrectArrayInitializer (loc);
return false;
}
return null;
if (arguments.Count != dimensions) {
- Error_IncorrectArrayInitializer ();
+ Error_IncorrectArrayInitializer (loc);
}
foreach (Argument a in arguments){
// If we are dealing with a struct, get the
// address of it, so we can store it.
//
- if ((dims == 1) && etype.IsValueType &&
+ if ((dims == 1) && TypeManager.IsStruct (etype) &&
(!TypeManager.IsBuiltinOrEnum (etype) ||
etype == TypeManager.decimal_type)) {
- if (e is New){
- New n = (New) e;
-
- //
- // Let new know that we are providing
- // the address where to store the results
- //
- n.DisableTemporaryValueType ();
- }
ig.Emit (OpCodes.Ldelema, etype);
}
return this;
}
- public override HoistedVariable HoistedVariable {
- get { return null; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return null;
}
}
get { return false; }
}
- protected override bool IsHoistedEmitRequired (EmitContext ec)
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
{
- //
- // Handle 'this' differently, it cannot be assigned hence
- // when we are not inside anonymous method we can emit direct access
- //
- return ec.CurrentAnonymousMethod != null && base.IsHoistedEmitRequired (ec);
- }
+ // Is null when probing IsHoisted
+ if (ec == null)
+ return null;
+
+ if (ec.CurrentAnonymousMethod == null)
+ return null;
- public override HoistedVariable HoistedVariable {
- get { return TopToplevelBlock.HoistedThisVariable; }
+ AnonymousMethodStorey storey = ec.CurrentAnonymousMethod.Storey;
+ while (storey != null) {
+ AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey;
+ if (temp == null)
+ return storey.HoistedThis;
+
+ storey = temp;
+ }
+
+ return null;
}
public override bool IsRef {
get { return ThisVariable.Instance; }
}
- // TODO: Move to ToplevelBlock
- ToplevelBlock TopToplevelBlock {
- get {
- ToplevelBlock tl = block.Toplevel;
- while (tl.Parent != null) tl = tl.Parent.Toplevel;
- return tl;
- }
- }
-
public static bool IsThisAvailable (EmitContext ec)
{
if (ec.IsStatic || ec.IsInFieldInitializer)
variable_info = block.Toplevel.ThisVariable.VariableInfo;
AnonymousExpression am = ec.CurrentAnonymousMethod;
- if (am != null) {
- //
- // this is hoisted to very top level block
- //
- if (ec.IsVariableCapturingRequired) {
- //
- // TODO: it should be optimized, see test-anon-75.cs
- //
- // `this' variable has its own scope which is mostly empty
- // and causes creation of extraneous storey references.
- // Also it's hard to remove `this' dependencies when we Undo
- // this access.
- //
- AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec);
- if (HoistedVariable == null) {
- TopToplevelBlock.HoistedThisVariable = scope.CaptureThis (ec, this);
- }
- }
+ if (am != null && ec.IsVariableCapturingRequired) {
+ am.SetHasThisAccess ();
}
}
//
public override void CheckMarshalByRefAccess (EmitContext ec)
{
- if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) &&
+ if ((variable_info != null) && !(TypeManager.IsStruct (type) && ec.OmitStructFlowAnalysis) &&
!variable_info.IsAssigned (ec)) {
Error (188, "The `this' object cannot be used before all of its " +
"fields are assigned to");
public override Expression CreateExpressionTree (EmitContext ec)
{
- ArrayList args = new ArrayList (2);
+ ArrayList args = new ArrayList (1);
args.Add (new Argument (this));
- args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+
+ // Use typeless constant for ldarg.0 to save some
+ // space and avoid problems with anonymous stories
return CreateExpressionFactoryCall ("Constant", args);
}
target.block = clonectx.LookupBlock (block);
}
- public void RemoveHoisting ()
- {
- TopToplevelBlock.HoistedThisVariable = null;
- }
-
public override void SetHasAddressTaken ()
{
// Nothing
this.expr = expr;
}
- // TODO: this method has very poor performace for Enum fields and
- // probably for other constants as well
Expression DoResolve (EmitContext ec, Expression right_side)
{
if (type != null)
string LookupIdentifier = MemberName.MakeName (Name, targs);
- if (expr_resolved is Namespace) {
- Namespace ns = (Namespace) expr_resolved;
+ Namespace ns = expr_resolved as Namespace;
+ if (ns != null) {
FullNamedExpression retval = ns.Lookup (ec.DeclContainer, LookupIdentifier, loc);
-#if GMCS_SOURCE
- if ((retval != null) && (targs != null))
- retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (ec, false);
-#endif
if (retval == null)
- ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, Name);
+ ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, LookupIdentifier);
+ else if (targs != null)
+ retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false);
+
return retval;
}
}
expr = expr_resolved;
- Error_MemberLookupFailed (
+ member_lookup = Error_MemberLookupFailed (
ec.ContainerType, expr_type, expr_type, Name, null,
AllMemberTypes, AllBindingFlags);
- return null;
+ if (member_lookup == null)
+ return null;
}
TypeExpr texpr = member_lookup as TypeExpr;
}
#if GMCS_SOURCE
- ConstructedType ct = expr_resolved as ConstructedType;
+ GenericTypeExpr ct = expr_resolved as GenericTypeExpr;
if (ct != null) {
//
// When looking up a nested type in a generic instance
//
// See gtest-172-lib.cs and gtest-172.cs for an example.
//
- ct = new ConstructedType (
+ ct = new GenericTypeExpr (
member_lookup.Type, ct.TypeArguments, loc);
return ct.ResolveAsTypeStep (ec, false);
public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent)
{
- FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent);
+ FullNamedExpression expr_resolved = expr.ResolveAsTypeStep (rc, silent);
- if (new_expr == null)
+ if (expr_resolved == null)
return null;
string LookupIdentifier = MemberName.MakeName (Name, targs);
- if (new_expr is Namespace) {
- Namespace ns = (Namespace) new_expr;
+ Namespace ns = expr_resolved as Namespace;
+ if (ns != null) {
FullNamedExpression retval = ns.Lookup (rc.DeclContainer, LookupIdentifier, loc);
-#if GMCS_SOURCE
- if ((retval != null) && (targs != null))
- retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (rc, false);
-#endif
- if (!silent && retval == null)
+
+ if (retval == null && !silent)
ns.Error_NamespaceDoesNotExist (rc.DeclContainer, loc, LookupIdentifier);
+ else if (targs != null)
+ retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent);
+
return retval;
}
- TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (rc, false);
+ TypeExpr tnew_expr = expr_resolved.ResolveAsTypeTerminal (rc, false);
if (tnew_expr == null)
return null;
if (silent)
return null;
- Error_IdentifierNotFound (rc, new_expr, LookupIdentifier);
+ Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier);
return null;
}
#if GMCS_SOURCE
TypeArguments the_args = targs;
Type declaring_type = texpr.Type.DeclaringType;
- if (TypeManager.HasGenericArguments (declaring_type)) {
+ if (TypeManager.HasGenericArguments (declaring_type) && !TypeManager.IsGenericTypeDefinition (expr_type)) {
while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) {
expr_type = expr_type.BaseType;
}
- TypeArguments new_args = new TypeArguments (loc);
+ TypeArguments new_args = new TypeArguments ();
foreach (Type decl in TypeManager.GetTypeArguments (expr_type))
new_args.Add (new TypeExpression (decl, loc));
}
if (the_args != null) {
- ConstructedType ctype = new ConstructedType (texpr.Type, the_args, loc);
+ GenericTypeExpr ctype = new GenericTypeExpr (texpr.Type, the_args, loc);
return ctype.ResolveAsTypeStep (rc, false);
}
#endif
if (expr_type == null)
return;
- Namespace.Error_TypeArgumentsCannotBeUsed (expr_type.Type, loc);
+ Namespace.Error_TypeArgumentsCannotBeUsed (expr_type, loc);
return;
}
if (type.IsPointer)
return MakePointerAccess (ec, type);
- if (Expr.eclass != ExprClass.Variable && type.IsValueType)
+ if (Expr.eclass != ExprClass.Variable && TypeManager.IsStruct (type))
Error_CannotModifyIntermediateExpressionValue (ec);
return (new IndexerAccess (this, loc)).DoResolveLValue (ec, right_side);
ig.Emit (OpCodes.Ldelem_I);
else if (TypeManager.IsEnumType (type)){
EmitLoadOpcode (ig, TypeManager.GetEnumUnderlyingType (type), rank);
- } else if (type.IsValueType){
+ } else if (TypeManager.IsStruct (type)){
ig.Emit (OpCodes.Ldelema, type);
ig.Emit (OpCodes.Ldobj, type);
#if GMCS_SOURCE
has_type_arg = true;
is_stobj = true;
return OpCodes.Stobj;
- } else if (t.IsValueType) {
+ } else if (TypeManager.IsStruct (t)) {
has_type_arg = true;
is_stobj = true;
return OpCodes.Stobj;
}
}
+ public void EmitNew (EmitContext ec, New source, bool leave_copy)
+ {
+ if (!source.Emit (ec, this)) {
+ if (leave_copy)
+ throw new NotImplementedException ();
+
+ return;
+ }
+
+ throw new NotImplementedException ();
+ }
+
public void AddressOf (EmitContext ec, AddressOp mode)
{
int rank = ea.Expr.Type.GetArrayRank ();
private EmptyExpressionStatement ()
{
- type = TypeManager.object_type;
eclass = ExprClass.Value;
loc = Location.Null;
}
public override Expression DoResolve (EmitContext ec)
{
+ type = TypeManager.object_type;
return this;
}
Type ltype = lexpr.Type;
#if GMCS_SOURCE
if ((dim.Length > 0) && (dim [0] == '?')) {
- TypeExpr nullable = new Nullable.NullableType (left, loc);
+ TypeExpr nullable = new Nullable.NullableType (lexpr, loc);
if (dim.Length > 1)
nullable = new ComposedCast (nullable, dim.Substring (1), loc);
return nullable.ResolveAsTypeTerminal (ec, false);
return left.GetSignatureForError () + dim;
}
- protected override void CloneTo (CloneContext clonectx, Expression t)
- {
- ComposedCast target = (ComposedCast) t;
-
- target.left = (FullNamedExpression)left.Clone (clonectx);
- }
-
public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
{
return ResolveAsBaseTerminal (ec, silent);
//
Constant c = source as Constant;
if (c != null && c.IsDefaultInitializer (type) && target.eclass == ExprClass.Variable)
- return EmptyExpressionStatement.Instance;
+ return EmptyExpressionStatement.Instance.DoResolve (ec);
return expr;
}
- protected override Expression Error_MemberLookupFailed (MemberInfo[] members)
+ protected override Expression Error_MemberLookupFailed (Type type, MemberInfo[] members)
{
MemberInfo member = members [0];
if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field)
public override void Emit (EmitContext ec)
{
- new_instance.value_target.Emit (ec);
+ Expression e = (Expression) new_instance.instance;
+ e.Emit (ec);
}
#region IMemoryLocation Members
public void AddressOf (EmitContext ec, AddressOp mode)
{
- ((IMemoryLocation)new_instance.value_target).AddressOf (ec, mode);
+ new_instance.instance.AddressOf (ec, mode);
}
#endregion
}
CollectionOrObjectInitializers initializers;
+ IMemoryLocation instance;
public NewInitialize (Expression requested_type, ArrayList arguments, CollectionOrObjectInitializers initializers, Location l)
: base (requested_type, arguments, l)
return e;
}
- public override void Emit (EmitContext ec)
+ public override bool Emit (EmitContext ec, IMemoryLocation target)
{
- base.Emit (ec);
+ bool left_on_stack = base.Emit (ec, target);
+
+ if (initializers.IsEmpty)
+ return left_on_stack;
+
+ LocalTemporary temp = null;
//
// If target is non-hoisted variable, let's use it
//
- VariableReference variable = value_target as VariableReference;
- if (variable != null && variable.HoistedVariable == null) {
- if (variable.IsRef)
- StoreFromPtr (ec.ig, type);
- else
- variable.EmitAssign (ec, EmptyExpression.Null, false, false);
- } else {
- variable = null;
- if (value_target == null || value_target_set)
- value_target = new LocalTemporary (type);
+ VariableReference variable = target as VariableReference;
+ if (variable != null) {
+ instance = target;
- ((LocalTemporary) value_target).Store (ec);
- }
+ if (left_on_stack) {
+ if (variable.IsRef)
+ StoreFromPtr (ec.ig, type);
+ else
+ variable.EmitAssign (ec, EmptyExpression.Null, false, false);
- initializers.Emit (ec);
+ left_on_stack = false;
+ }
+ } else {
+ temp = target as LocalTemporary;
+ if (temp == null) {
+ if (!left_on_stack)
+ throw new NotImplementedException ();
- if (variable == null) {
- value_target.Emit (ec);
- value_target = null;
- }
- }
+ temp = new LocalTemporary (type);
+ }
- public override void EmitStatement (EmitContext ec)
- {
- if (initializers.IsEmpty) {
- base.EmitStatement (ec);
- return;
+ instance = temp;
+ if (left_on_stack)
+ temp.Store (ec);
}
- base.Emit (ec);
+ initializers.Emit (ec);
- if (value_target == null) {
- LocalTemporary variable = new LocalTemporary (type);
- variable.Store (ec);
- value_target = variable;
+ if (left_on_stack) {
+ temp.Emit (ec);
+ temp.Release (ec);
}
- initializers.EmitStatement (ec);
+ return left_on_stack;
}
public override bool HasInitializer {
if (anonymous_type == null)
return null;
- ConstructedType te = new ConstructedType (anonymous_type.TypeBuilder,
- new TypeArguments (loc, t_args), loc);
+ GenericTypeExpr te = new GenericTypeExpr (anonymous_type.TypeBuilder,
+ new TypeArguments (t_args), loc);
return new New (te, arguments, loc).Resolve (ec);
}