Author: raja
Date: 2006-05-18 11:34:54 -0400 (Thu, 18 May 2006)
New Revision: 60827
Added:
trunk/mcs/tests/test-518.cs
Modified:
trunk/mcs/gmcs/ChangeLog
trunk/mcs/gmcs/flowanalysis.cs
trunk/mcs/gmcs/statement.cs
trunk/mcs/mcs/ChangeLog
trunk/mcs/mcs/flowanalysis.cs
trunk/mcs/mcs/statement.cs
trunk/mcs/tests/ChangeLog
Log:
In mcs:
Fix #77601
* statement.cs (Goto.Resolve): Move responsibility for resolving
'goto' to FlowBranching.AddGotoOrigin.
(Goto.SetResolvedTarget): New. Callback to set the
LabeledStatement that's the target of the goto.
(Goto.DoEmit): Use Leave instead of Br when crossing an
unwind-protect boundary.
* flowanalysis.cs (FlowBranching.AddGotoOrigin): Rename from
LookupLabel and adjust to new semantics.
(FlowBranchingToplevel.AddGotoOrigin): Likewise.
(FlowBranchingBlock.AddGotoOrigin): Likewise. Use
Goto.SetResolvedTarget to update target.
(FlowBranchingLabeled.AddGotoOrigin): Likewise.
(FlowBranchingException.AddGotoOrigin): Rewrite to be similar to
AddBreakOrigin & co. Delay propagation until ...
(FlowBranchingException.Merge): ... this.
In gmcs:
Fix #77601
* statement.cs (Goto.Resolve): Move responsibility for resolving
'goto' to FlowBranching.AddGotoOrigin.
(Goto.SetResolvedTarget): New. Callback to set the
LabeledStatement that's the target of the goto.
(Goto.DoEmit): Use Leave instead of Br when crossing an
unwind-protect boundary.
* flowanalysis.cs (FlowBranching.AddGotoOrigin): Rename from
LookupLabel and adjust to new semantics.
(FlowBranchingToplevel.AddGotoOrigin): Likewise.
(FlowBranchingBlock.AddGotoOrigin): Likewise. Use
Goto.SetResolvedTarget to update target.
(FlowBranchingLabeled.AddGotoOrigin): Likewise.
(FlowBranchingException.AddGotoOrigin): Rewrite to be similar to
AddBreakOrigin & co. Delay propagation until ...
(FlowBranchingException.Merge): ... this.
In tests:
* test-518.cs: New test based on #77601.
Modified: trunk/mcs/gmcs/ChangeLog
===================================================================
--- trunk/mcs/gmcs/ChangeLog 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/gmcs/ChangeLog 2006-05-18 15:34:54 UTC (rev 60827)
@@ -1,5 +1,22 @@
2006-05-18 Raja R Harinath <[EMAIL PROTECTED]>
+ Fix #77601
+ * statement.cs (Goto.Resolve): Move responsibility for resolving
+ 'goto' to FlowBranching.AddGotoOrigin.
+ (Goto.SetResolvedTarget): New. Callback to set the
+ LabeledStatement that's the target of the goto.
+ (Goto.DoEmit): Use Leave instead of Br when crossing an
+ unwind-protect boundary.
+ * flowanalysis.cs (FlowBranching.AddGotoOrigin): Rename from
+ LookupLabel and adjust to new semantics.
+ (FlowBranchingToplevel.AddGotoOrigin): Likewise.
+ (FlowBranchingBlock.AddGotoOrigin): Likewise. Use
+ Goto.SetResolvedTarget to update target.
+ (FlowBranchingLabeled.AddGotoOrigin): Likewise.
+ (FlowBranchingException.AddGotoOrigin): Rewrite to be similar to
+ AddBreakOrigin & co. Delay propagation until ...
+ (FlowBranchingException.Merge): ... this.
+
* statement.cs (Block.Resolve): Always depend on flow-branching to
determine unreachability. Kill workaround that originally emitted
only one statement after an "unreachable" label (see infloop in
Modified: trunk/mcs/gmcs/flowanalysis.cs
===================================================================
--- trunk/mcs/gmcs/flowanalysis.cs 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/gmcs/flowanalysis.cs 2006-05-18 15:34:54 UTC (rev 60827)
@@ -618,11 +618,6 @@
protected abstract void AddSibling (UsageVector uv);
- public virtual LabeledStatement LookupLabel (string name,
Location loc)
- {
- return Parent.LookupLabel (name, loc);
- }
-
protected abstract UsageVector Merge ();
// <summary>
@@ -661,6 +656,12 @@
return Parent.AddReturnOrigin (vector, loc);
}
+ // returns true if we crossed an unwind-protected region
(try/catch/finally, lock, using, ...)
+ public virtual bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
+ {
+ return Parent.AddGotoOrigin (vector, goto_stmt);
+ }
+
public virtual void StealFinallyClauses (ref ArrayList list)
{
Parent.StealFinallyClauses (ref list);
@@ -733,14 +734,16 @@
sibling_list = sibling;
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
{
- LabeledStatement stmt = Block == null ? null :
Block.LookupLabel (name);
+ LabeledStatement stmt = Block == null ? null :
Block.LookupLabel (goto_stmt.Target);
if (stmt == null)
- return Parent.LookupLabel (name, loc);
+ return Parent.AddGotoOrigin (vector, goto_stmt);
- stmt.AddReference ();
- return stmt;
+ // forward jump
+ goto_stmt.SetResolvedTarget (stmt);
+ stmt.AddUsageVector (vector);
+ return false;
}
protected override UsageVector Merge ()
@@ -802,7 +805,6 @@
public class FlowBranchingLabeled : FlowBranchingBlock
{
- bool unreachable, backward_jump;
LabeledStatement stmt;
UsageVector actual;
@@ -812,34 +814,30 @@
this.stmt = stmt;
CurrentUsageVector.MergeOrigins (stmt.JumpOrigins);
actual = CurrentUsageVector.Clone ();
- unreachable = actual.Reachability.IsUnreachable;
// stand-in for backward jumps
CurrentUsageVector.Reachability.Meet
(Reachability.Always ());
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
{
- if (name != stmt.Name)
- return Parent.LookupLabel (name, loc);
+ if (goto_stmt.Target != stmt.Name)
+ return Parent.AddGotoOrigin (vector, goto_stmt);
- unreachable = false;
- backward_jump = true;
+ // backward jump
+ goto_stmt.SetResolvedTarget (stmt);
+ actual.MergeOrigins (vector.Clone ());
- stmt.AddReference ();
- return stmt;
+ return false;
}
protected override UsageVector Merge ()
{
UsageVector vector = base.Merge ();
- if (unreachable)
+ if (actual.Reachability.IsUnreachable)
Report.Warning (162, 2, stmt.loc, "Unreachable
code detected");
- if (backward_jump)
- return vector;
-
actual.MergeChild (vector, false);
return actual;
}
@@ -899,22 +897,23 @@
// nothing to do
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
{
+ string name = goto_stmt.Target;
LabeledStatement s = Block.LookupLabel (name);
if (s != null)
throw new InternalErrorException ("Shouldn't
get here");
- if (Parent != null) {
- s = Parent.LookupLabel (name, loc);
- if (s != null) {
- Report.Error (1632, loc, "Control
cannot leave the body of an anonymous method");
- return null;
- }
+ if (Parent == null) {
+ Report.Error (159, goto_stmt.loc, "No such
label `{0}' in this scope", name);
+ return false;
}
- Report.Error (159, loc, "No such label `{0}' in this
scope", name);
- return null;
+ int errors = Report.Errors;
+ Parent.AddGotoOrigin (vector, goto_stmt);
+ if (errors == Report.Errors)
+ Report.Error (1632, goto_stmt.loc, "Control
cannot leave the body of an anonymous method");
+ return false;
}
public Reachability End ()
@@ -940,7 +939,21 @@
UsageVector break_origins;
UsageVector continue_origins;
UsageVector return_origins;
+ GotoOrigin goto_origins;
+ class GotoOrigin {
+ public GotoOrigin Next;
+ public Goto GotoStmt;
+ public UsageVector Vector;
+
+ public GotoOrigin (UsageVector vector, Goto goto_stmt,
GotoOrigin next)
+ {
+ Vector = vector;
+ GotoStmt = goto_stmt;
+ Next = next;
+ }
+ }
+
bool emit_finally;
public FlowBranchingException (FlowBranching parent,
@@ -1023,6 +1036,19 @@
return true;
}
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
+ {
+ LabeledStatement s = current_vector.Block == null ?
null : current_vector.Block.LookupLabel (goto_stmt.Target);
+ if (s != null)
+ throw new InternalErrorException ("Shouldn't
get here");
+
+ if (finally_vector != null)
+ Report.Error (157, goto_stmt.loc, "Control
cannot leave the body of a finally clause");
+ else
+ goto_origins = new GotoOrigin (vector.Clone (),
goto_stmt, goto_origins);
+ return true;
+ }
+
public override void StealFinallyClauses (ref ArrayList list)
{
if (list == null)
@@ -1036,23 +1062,6 @@
get { return emit_finally; }
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
- {
- if (current_vector.Block == null)
- return base.LookupLabel (name, loc);
-
- LabeledStatement s = current_vector.Block.LookupLabel
(name);
- if (s != null)
- return s;
-
- if (finally_vector != null) {
- Report.Error (157, loc, "Control cannot leave
the body of a finally clause");
- return null;
- }
-
- return base.LookupLabel (name, loc);
- }
-
protected override UsageVector Merge ()
{
Report.Debug (2, " MERGING TRY/CATCH", Name);
@@ -1083,6 +1092,13 @@
Parent.AddReturnOrigin (origin,
origin.Location);
}
+ for (GotoOrigin origin = goto_origins; origin != null;
origin = origin.Next) {
+ if (finally_vector != null)
+ origin.Vector.MergeChild
(finally_vector, false);
+ if (!origin.Vector.Reachability.IsUnreachable)
+ Parent.AddGotoOrigin (origin.Vector,
origin.GotoStmt);
+ }
+
return vector;
}
}
Modified: trunk/mcs/gmcs/statement.cs
===================================================================
--- trunk/mcs/gmcs/statement.cs 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/gmcs/statement.cs 2006-05-18 15:34:54 UTC (rev 60827)
@@ -582,7 +582,7 @@
loc = l;
}
- bool in_exc;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
@@ -624,8 +624,8 @@
}
int errors = Report.Errors;
- in_exc = ec.CurrentBranching.AddReturnOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
- if (in_exc)
+ unwind_protect = ec.CurrentBranching.AddReturnOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
+ if (unwind_protect)
ec.NeedReturnLabel ();
ec.CurrentBranching.CurrentUsageVector.Return ();
return errors == Report.Errors;
@@ -636,11 +636,11 @@
if (Expr != null) {
Expr.Emit (ec);
- if (in_exc)
+ if (unwind_protect)
ec.ig.Emit (OpCodes.Stloc,
ec.TemporaryReturn ());
}
- if (in_exc)
+ if (unwind_protect)
ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
else
ec.ig.Emit (OpCodes.Ret);
@@ -650,20 +650,14 @@
public class Goto : Statement {
string target;
LabeledStatement label;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
- label = ec.CurrentBranching.LookupLabel (target, loc);
- if (label == null)
- return false;
-
- // If this is a forward goto.
- if (!label.IsDefined)
- label.AddUsageVector
(ec.CurrentBranching.CurrentUsageVector);
-
+ int errors = Report.Errors;
+ unwind_protect = ec.CurrentBranching.AddGotoOrigin
(ec.CurrentBranching.CurrentUsageVector, this);
ec.CurrentBranching.CurrentUsageVector.Goto ();
-
- return true;
+ return errors == Report.Errors;
}
public Goto (string label, Location l)
@@ -676,10 +670,18 @@
get { return target; }
}
+ public void SetResolvedTarget (LabeledStatement label)
+ {
+ this.label = label;
+ label.AddReference ();
+ }
+
protected override void DoEmit (EmitContext ec)
{
+ if (label == null)
+ throw new InternalErrorException ("goto emitted
before target resolved");
Label l = label.LabelTarget (ec);
- ec.ig.Emit (OpCodes.Br, l);
+ ec.ig.Emit (unwind_protect ? OpCodes.Leave :
OpCodes.Br, l);
}
}
@@ -910,19 +912,19 @@
loc = l;
}
- bool crossing_exc;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
int errors = Report.Errors;
- crossing_exc = ec.CurrentBranching.AddBreakOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
+ unwind_protect = ec.CurrentBranching.AddBreakOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
ec.CurrentBranching.CurrentUsageVector.Goto ();
return errors == Report.Errors;
}
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (crossing_exc ? OpCodes.Leave : OpCodes.Br,
ec.LoopEnd);
+ ec.ig.Emit (unwind_protect ? OpCodes.Leave :
OpCodes.Br, ec.LoopEnd);
}
}
@@ -933,19 +935,19 @@
loc = l;
}
- bool crossing_exc;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
int errors = Report.Errors;
- crossing_exc = ec.CurrentBranching.AddContinueOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
+ unwind_protect = ec.CurrentBranching.AddContinueOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
ec.CurrentBranching.CurrentUsageVector.Goto ();
return errors == Report.Errors;
}
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (crossing_exc ? OpCodes.Leave : OpCodes.Br,
ec.LoopBegin);
+ ec.ig.Emit (unwind_protect ? OpCodes.Leave :
OpCodes.Br, ec.LoopBegin);
}
}
Modified: trunk/mcs/mcs/ChangeLog
===================================================================
--- trunk/mcs/mcs/ChangeLog 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/mcs/ChangeLog 2006-05-18 15:34:54 UTC (rev 60827)
@@ -1,5 +1,22 @@
2006-05-18 Raja R Harinath <[EMAIL PROTECTED]>
+ Fix #77601
+ * statement.cs (Goto.Resolve): Move responsibility for resolving
+ 'goto' to FlowBranching.AddGotoOrigin.
+ (Goto.SetResolvedTarget): New. Callback to set the
+ LabeledStatement that's the target of the goto.
+ (Goto.DoEmit): Use Leave instead of Br when crossing an
+ unwind-protect boundary.
+ * flowanalysis.cs (FlowBranching.AddGotoOrigin): Rename from
+ LookupLabel and adjust to new semantics.
+ (FlowBranchingToplevel.AddGotoOrigin): Likewise.
+ (FlowBranchingBlock.AddGotoOrigin): Likewise. Use
+ Goto.SetResolvedTarget to update target.
+ (FlowBranchingLabeled.AddGotoOrigin): Likewise.
+ (FlowBranchingException.AddGotoOrigin): Rewrite to be similar to
+ AddBreakOrigin & co. Delay propagation until ...
+ (FlowBranchingException.Merge): ... this.
+
* statement.cs (Block.Resolve): Always depend on flow-branching to
determine unreachability. Kill workaround that originally emitted
only one statement after an "unreachable" label (see infloop in
Modified: trunk/mcs/mcs/flowanalysis.cs
===================================================================
--- trunk/mcs/mcs/flowanalysis.cs 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/mcs/flowanalysis.cs 2006-05-18 15:34:54 UTC (rev 60827)
@@ -618,11 +618,6 @@
protected abstract void AddSibling (UsageVector uv);
- public virtual LabeledStatement LookupLabel (string name,
Location loc)
- {
- return Parent.LookupLabel (name, loc);
- }
-
protected abstract UsageVector Merge ();
// <summary>
@@ -661,6 +656,12 @@
return Parent.AddReturnOrigin (vector, loc);
}
+ // returns true if we crossed an unwind-protected region
(try/catch/finally, lock, using, ...)
+ public virtual bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
+ {
+ return Parent.AddGotoOrigin (vector, goto_stmt);
+ }
+
public virtual void StealFinallyClauses (ref ArrayList list)
{
Parent.StealFinallyClauses (ref list);
@@ -733,14 +734,16 @@
sibling_list = sibling;
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
{
- LabeledStatement stmt = Block == null ? null :
Block.LookupLabel (name);
+ LabeledStatement stmt = Block == null ? null :
Block.LookupLabel (goto_stmt.Target);
if (stmt == null)
- return Parent.LookupLabel (name, loc);
+ return Parent.AddGotoOrigin (vector, goto_stmt);
- stmt.AddReference ();
- return stmt;
+ // forward jump
+ goto_stmt.SetResolvedTarget (stmt);
+ stmt.AddUsageVector (vector);
+ return false;
}
protected override UsageVector Merge ()
@@ -802,7 +805,6 @@
public class FlowBranchingLabeled : FlowBranchingBlock
{
- bool unreachable, backward_jump;
LabeledStatement stmt;
UsageVector actual;
@@ -812,34 +814,30 @@
this.stmt = stmt;
CurrentUsageVector.MergeOrigins (stmt.JumpOrigins);
actual = CurrentUsageVector.Clone ();
- unreachable = actual.Reachability.IsUnreachable;
// stand-in for backward jumps
CurrentUsageVector.Reachability.Meet
(Reachability.Always ());
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
{
- if (name != stmt.Name)
- return Parent.LookupLabel (name, loc);
+ if (goto_stmt.Target != stmt.Name)
+ return Parent.AddGotoOrigin (vector, goto_stmt);
- unreachable = false;
- backward_jump = true;
+ // backward jump
+ goto_stmt.SetResolvedTarget (stmt);
+ actual.MergeOrigins (vector.Clone ());
- stmt.AddReference ();
- return stmt;
+ return false;
}
protected override UsageVector Merge ()
{
UsageVector vector = base.Merge ();
- if (unreachable)
+ if (actual.Reachability.IsUnreachable)
Report.Warning (162, 2, stmt.loc, "Unreachable
code detected");
- if (backward_jump)
- return vector;
-
actual.MergeChild (vector, false);
return actual;
}
@@ -899,22 +897,23 @@
// nothing to do
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
{
+ string name = goto_stmt.Target;
LabeledStatement s = Block.LookupLabel (name);
if (s != null)
throw new InternalErrorException ("Shouldn't
get here");
- if (Parent != null) {
- s = Parent.LookupLabel (name, loc);
- if (s != null) {
- Report.Error (1632, loc, "Control
cannot leave the body of an anonymous method");
- return null;
- }
+ if (Parent == null) {
+ Report.Error (159, goto_stmt.loc, "No such
label `{0}' in this scope", name);
+ return false;
}
- Report.Error (159, loc, "No such label `{0}' in this
scope", name);
- return null;
+ int errors = Report.Errors;
+ Parent.AddGotoOrigin (vector, goto_stmt);
+ if (errors == Report.Errors)
+ Report.Error (1632, goto_stmt.loc, "Control
cannot leave the body of an anonymous method");
+ return false;
}
public Reachability End ()
@@ -940,7 +939,21 @@
UsageVector break_origins;
UsageVector continue_origins;
UsageVector return_origins;
+ GotoOrigin goto_origins;
+ class GotoOrigin {
+ public GotoOrigin Next;
+ public Goto GotoStmt;
+ public UsageVector Vector;
+
+ public GotoOrigin (UsageVector vector, Goto goto_stmt,
GotoOrigin next)
+ {
+ Vector = vector;
+ GotoStmt = goto_stmt;
+ Next = next;
+ }
+ }
+
bool emit_finally;
public FlowBranchingException (FlowBranching parent,
@@ -1023,6 +1036,19 @@
return true;
}
+ public override bool AddGotoOrigin (UsageVector vector, Goto
goto_stmt)
+ {
+ LabeledStatement s = current_vector.Block == null ?
null : current_vector.Block.LookupLabel (goto_stmt.Target);
+ if (s != null)
+ throw new InternalErrorException ("Shouldn't
get here");
+
+ if (finally_vector != null)
+ Report.Error (157, goto_stmt.loc, "Control
cannot leave the body of a finally clause");
+ else
+ goto_origins = new GotoOrigin (vector.Clone (),
goto_stmt, goto_origins);
+ return true;
+ }
+
public override void StealFinallyClauses (ref ArrayList list)
{
if (list == null)
@@ -1036,23 +1062,6 @@
get { return emit_finally; }
}
- public override LabeledStatement LookupLabel (string name,
Location loc)
- {
- if (current_vector.Block == null)
- return base.LookupLabel (name, loc);
-
- LabeledStatement s = current_vector.Block.LookupLabel
(name);
- if (s != null)
- return s;
-
- if (finally_vector != null) {
- Report.Error (157, loc, "Control cannot leave
the body of a finally clause");
- return null;
- }
-
- return base.LookupLabel (name, loc);
- }
-
protected override UsageVector Merge ()
{
Report.Debug (2, " MERGING TRY/CATCH", Name);
@@ -1083,6 +1092,13 @@
Parent.AddReturnOrigin (origin,
origin.Location);
}
+ for (GotoOrigin origin = goto_origins; origin != null;
origin = origin.Next) {
+ if (finally_vector != null)
+ origin.Vector.MergeChild
(finally_vector, false);
+ if (!origin.Vector.Reachability.IsUnreachable)
+ Parent.AddGotoOrigin (origin.Vector,
origin.GotoStmt);
+ }
+
return vector;
}
}
Modified: trunk/mcs/mcs/statement.cs
===================================================================
--- trunk/mcs/mcs/statement.cs 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/mcs/statement.cs 2006-05-18 15:34:54 UTC (rev 60827)
@@ -582,7 +582,7 @@
loc = l;
}
- bool in_exc;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
@@ -624,8 +624,8 @@
}
int errors = Report.Errors;
- in_exc = ec.CurrentBranching.AddReturnOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
- if (in_exc)
+ unwind_protect = ec.CurrentBranching.AddReturnOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
+ if (unwind_protect)
ec.NeedReturnLabel ();
ec.CurrentBranching.CurrentUsageVector.Return ();
return errors == Report.Errors;
@@ -636,11 +636,11 @@
if (Expr != null) {
Expr.Emit (ec);
- if (in_exc)
+ if (unwind_protect)
ec.ig.Emit (OpCodes.Stloc,
ec.TemporaryReturn ());
}
- if (in_exc)
+ if (unwind_protect)
ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
else
ec.ig.Emit (OpCodes.Ret);
@@ -650,20 +650,14 @@
public class Goto : Statement {
string target;
LabeledStatement label;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
- label = ec.CurrentBranching.LookupLabel (target, loc);
- if (label == null)
- return false;
-
- // If this is a forward goto.
- if (!label.IsDefined)
- label.AddUsageVector
(ec.CurrentBranching.CurrentUsageVector);
-
+ int errors = Report.Errors;
+ unwind_protect = ec.CurrentBranching.AddGotoOrigin
(ec.CurrentBranching.CurrentUsageVector, this);
ec.CurrentBranching.CurrentUsageVector.Goto ();
-
- return true;
+ return errors == Report.Errors;
}
public Goto (string label, Location l)
@@ -676,10 +670,18 @@
get { return target; }
}
+ public void SetResolvedTarget (LabeledStatement label)
+ {
+ this.label = label;
+ label.AddReference ();
+ }
+
protected override void DoEmit (EmitContext ec)
{
+ if (label == null)
+ throw new InternalErrorException ("goto emitted
before target resolved");
Label l = label.LabelTarget (ec);
- ec.ig.Emit (OpCodes.Br, l);
+ ec.ig.Emit (unwind_protect ? OpCodes.Leave :
OpCodes.Br, l);
}
}
@@ -910,19 +912,19 @@
loc = l;
}
- bool crossing_exc;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
int errors = Report.Errors;
- crossing_exc = ec.CurrentBranching.AddBreakOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
+ unwind_protect = ec.CurrentBranching.AddBreakOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
ec.CurrentBranching.CurrentUsageVector.Goto ();
return errors == Report.Errors;
}
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (crossing_exc ? OpCodes.Leave : OpCodes.Br,
ec.LoopEnd);
+ ec.ig.Emit (unwind_protect ? OpCodes.Leave :
OpCodes.Br, ec.LoopEnd);
}
}
@@ -933,19 +935,19 @@
loc = l;
}
- bool crossing_exc;
+ bool unwind_protect;
public override bool Resolve (EmitContext ec)
{
int errors = Report.Errors;
- crossing_exc = ec.CurrentBranching.AddContinueOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
+ unwind_protect = ec.CurrentBranching.AddContinueOrigin
(ec.CurrentBranching.CurrentUsageVector, loc);
ec.CurrentBranching.CurrentUsageVector.Goto ();
return errors == Report.Errors;
}
protected override void DoEmit (EmitContext ec)
{
- ec.ig.Emit (crossing_exc ? OpCodes.Leave : OpCodes.Br,
ec.LoopBegin);
+ ec.ig.Emit (unwind_protect ? OpCodes.Leave :
OpCodes.Br, ec.LoopBegin);
}
}
Modified: trunk/mcs/tests/ChangeLog
===================================================================
--- trunk/mcs/tests/ChangeLog 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/tests/ChangeLog 2006-05-18 15:34:54 UTC (rev 60827)
@@ -1,5 +1,7 @@
2006-05-18 Raja R Harinath <[EMAIL PROTECTED]>
+ * test-518.cs: New test based on #77601.
+
* test-514.cs: New test from #76148.
* test-515.cs, test-516.cs: New tests based on #77755.
* test-517.cs: New test based on #75255.
Added: trunk/mcs/tests/test-518.cs
===================================================================
--- trunk/mcs/tests/test-518.cs 2006-05-18 15:32:59 UTC (rev 60826)
+++ trunk/mcs/tests/test-518.cs 2006-05-18 15:34:54 UTC (rev 60827)
@@ -0,0 +1,14 @@
+class Foo {
+ static int Main ()
+ {
+ int ret = 1;
+ try {
+ goto done;
+ } finally {
+ ret = 0;
+ }
+ done:
+ return ret;
+ }
+}
+
Property changes on: trunk/mcs/tests/test-518.cs
___________________________________________________________________
Name: svn:eol-style
+ native
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches