var da_false = new DefiniteAssignmentBitSet (fc.DefiniteAssignmentOnFalse);
fc.DefiniteAssignment = fc.DefiniteAssignmentOnTrue;
+ var labels = fc.CopyLabelStack ();
var res = TrueStatement.FlowAnalysis (fc);
+ fc.SetLabelStack (labels);
+
if (FalseStatement == null) {
+
var c = expr as Constant;
if (c != null && !c.IsDefaultValue)
return true_returns;
if (true_returns) {
fc.DefiniteAssignment = da_false;
- return FalseStatement.FlowAnalysis (fc);
+
+ res = FalseStatement.FlowAnalysis (fc);
+ fc.SetLabelStack (labels);
+ return res;
}
var da_true = fc.DefiniteAssignment;
fc.DefiniteAssignment = da_false;
+
res &= FalseStatement.FlowAnalysis (fc);
+ fc.SetLabelStack (labels);
+
if (!TrueStatement.IsUnreachable) {
if (false_returns || FalseStatement.IsUnreachable)
fc.DefiniteAssignment = da_true;
public override void Emit (EmitContext ec)
{
+ if (!Variable.IsUsed)
+ ec.Report.Warning (219, 3, loc, "The constant `{0}' is never used", Variable.Name);
+
// Nothing to emit, not even sequence point
}
}
}
+ public bool IsUsed {
+ get {
+ return (flags & Flags.Used) != 0;
+ }
+ }
+
public bool IsFixed {
get {
return (flags & Flags.FixedVariable) != 0;
public Expression CreateReferenceExpression (ResolveContext rc, Location loc)
{
- if (IsConstant && const_value != null)
+ if (IsConstant && const_value != null) {
+ SetIsUsed ();
return Constant.CreateConstantFromValue (Type, const_value.GetValue (), loc);
+ }
return new LocalVariableReference (this, loc);
}
AwaitBlock = 1 << 13,
FinallyBlock = 1 << 14,
CatchBlock = 1 << 15,
+ HasReferenceToStoreyForInstanceLambdas = 1 << 16,
Iterator = 1 << 20,
NoFlowAnalysis = 1 << 21,
InitializationEmitted = 1 << 22
public override void Emit (EmitContext ec)
{
- if (Parent != null) {
- // TODO: It's needed only when scope has variable (normal or lifted)
- ec.BeginScope (GetDebugSymbolScopeIndex ());
+ // TODO: It's needed only when scope has variable (normal or lifted)
+ var scopeIndex = GetDebugSymbolScopeIndex ();
+ if (scopeIndex > 0) {
+ ec.BeginScope (scopeIndex);
}
EmitScopeInitialization (ec);
DoEmit (ec);
- if (Parent != null)
+ if (scopeIndex > 0)
ec.EndScope ();
if (ec.EmitAccurateDebugInfo && HasReachableClosingBrace && !(this is ParametersBlock) &&
//
storey.CreateContainer ();
storey.DefineContainer ();
+ storey.ExpandBaseInterfaces ();
if (Original.Explicit.HasCapturedThis && Original.ParametersBlock.TopBlock.ThisReferencesFromChildrenBlock != null) {
break;
}
}
-
+
//
// We are the first storey on path and 'this' has to be hoisted
//
//
// If we are state machine with no parent. We can hook into parent without additional
- // reference and capture this directly
+ // reference and capture this directly
//
ExplicitBlock parent_storey_block = pb;
while (parent_storey_block.Parent != null) {
storey.Parent.PartialContainer.AddCompilerGeneratedClass (storey);
}
- public int GetDebugSymbolScopeIndex ()
+ public void DisableDebugScopeIndex ()
+ {
+ debug_scope_index = -1;
+ }
+
+ public virtual int GetDebugSymbolScopeIndex ()
{
if (debug_scope_index == 0)
debug_scope_index = ++ParametersBlock.debug_scope_index;
#region Properties
+ public bool HasReferenceToStoreyForInstanceLambdas {
+ get {
+ return (flags & Flags.HasReferenceToStoreyForInstanceLambdas) != 0;
+ }
+ set {
+ flags = value ? flags | Flags.HasReferenceToStoreyForInstanceLambdas : flags & ~Flags.HasReferenceToStoreyForInstanceLambdas;
+ }
+ }
+
public bool IsAsync {
get {
return (flags & Flags.HasAsyncModifier) != 0;
return res;
}
+ public override int GetDebugSymbolScopeIndex ()
+ {
+ return 0;
+ }
+
public LabeledStatement GetLabel (string name, Block block)
{
//
ec.EmitInt (first_resume_pc);
ec.Emit (OpCodes.Sub);
- var labels = new Label[resume_points.Count - System.Math.Max (first_catch_resume_pc, 0)];
+ var labels = new Label [first_catch_resume_pc > 0 ? first_catch_resume_pc : resume_points.Count];
for (int i = 0; i < labels.Length; ++i)
labels[i] = resume_points[i].PrepareForEmit (ec);
ec.Emit (OpCodes.Switch, labels);
ec.LoopBegin = ec.DefineLabel ();
ec.LoopEnd = ec.DefineLabel ();
- if (!(Statement is Block))
- ec.BeginCompilerScope (variable.Block.Explicit.GetDebugSymbolScopeIndex ());
+ ec.BeginCompilerScope (variable.Block.Explicit.GetDebugSymbolScopeIndex ());
+ body.Explicit.DisableDebugScopeIndex ();
variable.CreateBuilder (ec);
Statement.Emit (ec);
- if (!(Statement is Block))
- ec.EndScope ();
+ ec.EndScope ();
ec.LoopBegin = old_begin;
ec.LoopEnd = old_end;