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));
}
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) && (right is NullLiteral || TypeManager.IsNullableType (right.Type) || TypeManager.IsValueType (right.Type))) ||
- (left.Type.IsValueType && right is NullLiteral) ||
+ (TypeManager.IsValueType (left.Type) && right is NullLiteral) ||
(TypeManager.IsNullableType (right.Type) && (left is NullLiteral || TypeManager.IsNullableType (left.Type) || TypeManager.IsValueType (left.Type))) ||
- (right.Type.IsValueType && left is NullLiteral)))
+ (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)
{
- 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;
}
}
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);
return null;
}
- bool is_struct = type.IsValueType;
+ bool is_struct = TypeManager.IsStruct (type);
eclass = ExprClass.Value;
//
return;
}
- if (!type.IsValueType){
+ if (!TypeManager.IsStruct (type)){
//
// We throw an exception. So far, I believe we only need to support
// value types:
// 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)) {
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;
+
+ AnonymousMethodStorey storey = ec.CurrentAnonymousMethod.Storey;
+ while (storey != null) {
+ AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey;
+ if (temp == null)
+ return storey.HoistedThis;
- public override HoistedVariable HoistedVariable {
- get { return TopToplevelBlock.HoistedThisVariable; }
+ 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");
target.block = clonectx.LookupBlock (block);
}
- public void RemoveHoisting ()
- {
- TopToplevelBlock.HoistedThisVariable = null;
- }
-
public override void SetHasAddressTaken ()
{
// Nothing
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;