- public IList<ToplevelBlock> AnonymousChildren {
- get { return anonymous_children; }
- }
-
- public void AddAnonymousChild (ToplevelBlock b)
- {
- if (anonymous_children == null)
- anonymous_children = new List<ToplevelBlock> ();
-
- anonymous_children.Add (b);
- }
-
- void DoResolveConstants (BlockContext ec)
- {
- if (constants == null)
- return;
-
- if (variables == null)
- throw new InternalErrorException ("cannot happen");
-
- foreach (var de in variables) {
- string name = de.Key;
- LocalInfo vi = de.Value;
- TypeSpec variable_type = vi.VariableType;
-
- if (variable_type == null) {
- if (vi.Type is VarExpr)
- ec.Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant");
-
- continue;
- }
-
- Expression cv;
- if (!constants.TryGetValue (name, out cv))
- continue;
-
- // Don't let 'const int Foo = Foo;' succeed.
- // Removing the name from 'constants' ensures that we get a LocalVariableReference below,
- // which in turn causes the 'must be constant' error to be triggered.
- constants.Remove (name);
-
- if (!variable_type.IsConstantCompatible) {
- Const.Error_InvalidConstantType (variable_type, loc, ec.Report);
- continue;
- }
-
- ec.CurrentBlock = this;
- Expression e;
- using (ec.With (ResolveContext.Options.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
- using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- e = cv.Resolve (ec);
- }
- }
- if (e == null)
- continue;
-
- Constant ce = e as Constant;
- if (ce == null) {
- e.Error_ExpressionMustBeConstant (ec, vi.Location, name);
- continue;
- }
-
- e = ce.ConvertImplicitly (ec, variable_type);
- if (e == null) {
- if (TypeManager.IsReferenceType (variable_type))
- ce.Error_ConstantCanBeInitializedWithNullOnly (ec, variable_type, vi.Location, vi.Name);
- else
- ce.Error_ValueCannotBeConverted (ec, vi.Location, variable_type, false);
- continue;
- }
-
- constants.Add (name, e);
- vi.IsConstant = true;
- }
- }
-
- protected void ResolveMeta (BlockContext ec, int offset)
- {
- Report.Debug (64, "BLOCK RESOLVE META", this, Parent);
-
- // If some parent block was unsafe, we remain unsafe even if this block
- // isn't explicitly marked as such.
- using (ec.With (ResolveContext.Options.UnsafeScope, ec.IsUnsafe | Unsafe)) {
- flags |= Flags.VariablesInitialized;
-
- if (variables != null) {
- foreach (LocalInfo li in variables.Values) {
- if (!li.Resolve (ec))
- continue;
- li.VariableInfo = new VariableInfo (li, offset);
- offset += li.VariableInfo.Length;
- }
- }
- assignable_slots = offset;
-
- DoResolveConstants (ec);
-
- if (children == null)
- return;
- foreach (Block b in children)
- b.ResolveMeta (ec, offset);
- }
- }
-
- //
- // Emits the local variable declarations for a block
- //
- public virtual void EmitMeta (EmitContext ec)
- {
- if (variables != null){
- foreach (LocalInfo vi in variables.Values)
- vi.ResolveVariable (ec);
- }
-
- if (temporary_variables != null) {
- for (int i = 0; i < temporary_variables.Count; i++)
- ((LocalInfo)temporary_variables[i]).ResolveVariable(ec);
- }
-
- if (children != null) {
- for (int i = 0; i < children.Count; i++)
- ((Block)children[i]).EmitMeta(ec);
- }
- }
-
- void UsageWarning (BlockContext ec)