public override bool Resolve (BlockContext ec)
{
Block prev_block = ec.CurrentBlock;
bool ok = true;
ec.CurrentBlock = this;
ec.StartFlowBranching (this);
Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
//
// Compiler generated scope statements
//
if (scope_initializers != null) {
for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) {
scope_initializers[resolving_init_idx.Value].Resolve (ec);
}
resolving_init_idx = null;
}
//
// This flag is used to notate nested statements as unreachable from the beginning of this block.
// For the purposes of this resolution, it doesn't matter that the whole block is unreachable
// from the beginning of the function. The outer Resolve() that detected the unreachability is
// responsible for handling the situation.
//
int statement_count = statements.Count;
for (int ix = 0; ix < statement_count; ix++){
Statement s = statements [ix];
//
// Warn if we detect unreachable code.
//
if (unreachable) {
if (s is EmptyStatement)
continue;
if (!unreachable_shown && !(s is LabeledStatement)) {
ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
unreachable_shown = true;
}
Block c_block = s as Block;
if (c_block != null)
c_block.unreachable = c_block.unreachable_shown = true;
}
//
// Note that we're not using ResolveUnreachable() for unreachable
// statements here. ResolveUnreachable() creates a temporary
// flow branching and kills it afterwards. This leads to problems
// if you have two unreachable statements where the first one
// assigns a variable and the second one tries to access it.
//
if (!s.Resolve (ec)) {
ok = false;
if (ec.IsInProbingMode)
break;
statements [ix] = new EmptyStatement (s.loc);
continue;
}
if (unreachable && !(s is LabeledStatement) && !(s is Block))
statements [ix] = new EmptyStatement (s.loc);
unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
if (unreachable && s is LabeledStatement)
throw new InternalErrorException ("should not happen");
}
Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
ec.CurrentBranching, statement_count);
while (ec.CurrentBranching is FlowBranchingLabeled)
ec.EndFlowBranching ();
bool flow_unreachable = ec.EndFlowBranching ();
ec.CurrentBlock = prev_block;
if (flow_unreachable)
flags |= Flags.HasRet;
// If we're a non-static `struct' constructor which doesn't have an
// initializer, then we must initialize all of the struct's fields.
if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable)
ok = false;
return ok;
}