//
using System;
-using System.Text;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Diagnostics;
using System.Collections.Generic;
+#if STATIC
+using IKVM.Reflection.Emit;
+#else
+using System.Reflection.Emit;
+#endif
+
namespace Mono.CSharp {
public abstract class Statement {
FixedVariable = 1 << 6,
UsingVariable = 1 << 7,
// DefinitelyAssigned = 1 << 8,
+ IsLocked = 1 << 9,
ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable
}
#region Properties
+ public bool AddressTaken {
+ get { return (flags & Flags.AddressTaken) != 0; }
+ set { flags |= Flags.AddressTaken; }
+ }
+
public Block Block {
get {
return block;
}
}
+ public bool IsLocked {
+ get {
+ return (flags & Flags.IsLocked) != 0;
+ }
+ set {
+ flags = value ? flags | Flags.IsLocked : flags & ~Flags.IsLocked;
+ }
+ }
+
public bool IsThis {
get {
return (flags & Flags.IsThis) != 0;
ec.Emit (OpCodes.Ldloca, builder);
}
+ public string GetReadOnlyContext ()
+ {
+ switch (flags & Flags.ReadonlyMask) {
+ case Flags.FixedVariable:
+ return "fixed variable";
+ case Flags.ForeachVariable:
+ return "foreach iteration variable";
+ case Flags.UsingVariable:
+ return "using variable";
+ }
+
+ throw new InternalErrorException ("Variable is not readonly");
+ }
+
public bool IsThisAssigned (BlockContext ec, Block block)
{
if (VariableInfo == null)
flags |= Flags.Used;
}
- public bool AddressTaken {
- get { return (flags & Flags.AddressTaken) != 0; }
- set { flags |= Flags.AddressTaken; }
- }
-
public override string ToString ()
{
return string.Format ("LocalInfo ({0},{1},{2},{3})", name, type, VariableInfo, Location);
}
-
- public string GetReadOnlyContext ()
- {
- switch (flags & Flags.ReadonlyMask) {
- case Flags.FixedVariable:
- return "fixed variable";
- case Flags.ForeachVariable:
- return "foreach iteration variable";
- case Flags.UsingVariable:
- return "using variable";
- }
-
- throw new InternalErrorException ("Variable is not readonly");
- }
}
/// <summary>
readonly ParametersBlock block;
readonly int index;
public VariableInfo VariableInfo;
+ bool is_locked;
public ParameterInfo (ParametersBlock block, int index)
{
}
}
+ public bool IsLocked {
+ get {
+ return is_locked;
+ }
+ set {
+ is_locked = value;
+ }
+ }
+
public Location Location {
get {
return Parameter.Location;
public SwitchLabel Clone (CloneContext clonectx)
{
+ if (label == null)
+ return this;
+
return new SwitchLabel (label.Clone (clonectx), loc);
}
}
{
var cloned_labels = new List<SwitchLabel> ();
- foreach (SwitchLabel sl in cloned_labels)
+ foreach (SwitchLabel sl in Labels)
cloned_labels.Add (sl.Clone (clonectx));
return new SwitchSection (cloned_labels, clonectx.LookupBlock (Block));
ec.Report.Error (185, loc,
"`{0}' is not a reference type as required by the lock statement",
expr.Type.GetSignatureForError ());
- return false;
+ }
+
+ if (expr.Type.IsGenericParameter) {
+ expr = Convert.ImplicitTypeParameterConversion (expr, TypeManager.object_type);
+ }
+
+ VariableReference lv = expr as VariableReference;
+ bool locked;
+ if (lv != null) {
+ locked = lv.IsLockedByStatement;
+ lv.IsLockedByStatement = true;
+ } else {
+ lv = null;
+ locked = false;
}
ec.StartFlowBranching (this);
- bool ok = Statement.Resolve (ec);
+ Statement.Resolve (ec);
ec.EndFlowBranching ();
- ok &= base.Resolve (ec);
+ if (lv != null) {
+ lv.IsLockedByStatement = locked;
+ }
+
+ base.Resolve (ec);
//
// Have to keep original lock value around to unlock same location
// in the case the original has changed or is null
//
- expr_copy = TemporaryVariableReference.Create (expr.Type, ec.CurrentBlock.Parent, loc);
+ expr_copy = TemporaryVariableReference.Create (TypeManager.object_type, ec.CurrentBlock.Parent, loc);
expr_copy.Resolve (ec);
//
lock_taken.Resolve (ec);
}
- return ok;
+ return true;
}
protected override void EmitPreTryBody (EmitContext ec)
{
expr_copy.EmitAssign (ec, expr);
- lock_taken.EmitAssign (ec, new BoolLiteral (false, loc));
+
+ if (lock_taken != null) {
+ //
+ // Initialize ref variable
+ //
+ lock_taken.EmitAssign (ec, new BoolLiteral (false, loc));
+ } else {
+ //
+ // Monitor.Enter (expr_copy)
+ //
+ expr_copy.Emit (ec);
+ ec.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
+ }
}
protected override void EmitTryBody (EmitContext ec)
//
// Monitor.Enter (expr_copy, ref lock_taken)
//
- expr_copy.Emit (ec);
-
if (lock_taken != null) {
+ expr_copy.Emit (ec);
lock_taken.LocalInfo.CreateBuilder (ec);
lock_taken.AddressOf (ec, AddressOp.Load);
+ ec.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
}
- ec.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
-
Statement.Emit (ec);
}
int ResolvePredefinedMethods (ResolveContext rc)
{
if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) {
- TypeSpec monitor_type = TypeManager.CoreLookupType (rc.Compiler, "System.Threading", "Monitor", MemberKind.Class, true);
+ TypeSpec monitor_type = rc.Module.PredefinedTypes.Monitor.Resolve (loc);
if (monitor_type == null)
return 0;
pinned_string.Type = TypeManager.string_type;
if (TypeManager.int_get_offset_to_string_data == null) {
- TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (
- TypeManager.runtime_helpers_type, "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
+ var helper = rc.Module.PredefinedTypes.RuntimeHelpers.Resolve (loc);
+ if (helper != null) {
+ TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (helper,
+ "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
+ }
}
eclass = ExprClass.Variable;
}
if (General != null) {
- if (CodeGen.Assembly.WrapNonExceptionThrows) {
- foreach (Catch c in Specific){
- if (c.CatchType == TypeManager.exception_type && ec.Compiler.PredefinedAttributes.RuntimeCompatibility.IsDefined) {
- ec.Report.Warning (1058, 1, c.loc,
- "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
- }
- }
+ foreach (Catch c in Specific) {
+ if (c.CatchType != TypeManager.exception_type)
+ continue;
+
+ if (!ec.Module.DeclaringAssembly.WrapNonExceptionThrows)
+ continue;
+
+ if (!ec.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined)
+ continue;
+
+ ec.Report.Warning (1058, 1, c.loc,
+ "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
}
ec.CurrentBranching.CreateSibling (General.Block, FlowBranching.SiblingType.Catch);
return base.Resolve (bc);
}
- public void ResolveExpression (BlockContext bc)
+ public Expression ResolveExpression (BlockContext bc)
{
var e = Initializer.Resolve (bc);
if (e == null)
- return;
+ return null;
li = LocalVariable.CreateCompilerGenerated (e.Type, bc.CurrentBlock, loc);
Initializer = ResolveInitializer (bc, Variable, e);
+ return e;
}
protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer)
public override bool Resolve (BlockContext ec)
{
+ VariableReference vr;
+ bool vr_locked = false;
+
using (ec.Set (ResolveContext.Options.UsingInitializerScope)) {
if (decl.Variable == null) {
- decl.ResolveExpression (ec);
+ vr = decl.ResolveExpression (ec) as VariableReference;
+ if (vr != null) {
+ vr_locked = vr.IsLockedByStatement;
+ vr.IsLockedByStatement = true;
+ }
} else {
if (!decl.Resolve (ec))
return false;
if (decl.Declarators != null) {
stmt = decl.RewriteForDeclarators (ec, stmt);
}
+
+ vr = null;
}
}
ec.StartFlowBranching (this);
- bool ok = stmt.Resolve (ec);
+ stmt.Resolve (ec);
ec.EndFlowBranching ();
- ok &= base.Resolve (ec);
+ if (vr != null)
+ vr.IsLockedByStatement = vr_locked;
- return ok;
+ base.Resolve (ec);
+
+ return true;
}
protected override void CloneTo (CloneContext clonectx, Statement t)
// Option 2: Try to match using IEnumerable interfaces with preference of generic version
//
TypeSpec iface_candidate = null;
- for (TypeSpec t = expr.Type; t != null && t != TypeManager.object_type; t = t.BaseType) {
+ var t = expr.Type;
+ do {
var ifaces = t.Interfaces;
if (ifaces != null) {
foreach (var iface in ifaces) {
}
}
}
- }
+
+ if (t.IsGenericParameter)
+ t = t.BaseType;
+ else
+ t = null;
+
+ } while (t != null);
if (iface_candidate == null) {
rc.Report.Error (1579, loc,