X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fstatement.cs;h=9a3121ecae27fc9f2cd6ecef0fde5f0eaae55588;hb=75e27c6abf4cb612f7945c861d227382498737f1;hp=96e486905b6736a71605031d57f83e4f2ae2a5a0;hpb=21ea6a285c37b8a22bf58a567486960df727ac2a;p=mono.git diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index 96e486905b6..9a3121ecae2 100644 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -103,6 +103,12 @@ namespace Mono.CSharp { return s; } + public virtual Expression CreateExpressionTree (EmitContext ec) + { + Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree"); + return null; + } + public Statement PerformClone () { CloneContext clonectx = new CloneContext (); @@ -209,21 +215,21 @@ namespace Mono.CSharp { bool is_true_ret; - public If (Expression expr, Statement trueStatement, Location l) + public If (Expression expr, Statement true_statement, Location l) { this.expr = expr; - TrueStatement = trueStatement; + TrueStatement = true_statement; loc = l; } public If (Expression expr, - Statement trueStatement, - Statement falseStatement, + Statement true_statement, + Statement false_statement, Location l) { this.expr = expr; - TrueStatement = trueStatement; - FalseStatement = falseStatement; + TrueStatement = true_statement; + FalseStatement = false_statement; loc = l; } @@ -247,8 +253,8 @@ namespace Mono.CSharp { // // Dead code elimination // - if (expr is BoolConstant){ - bool take = ((BoolConstant) expr).Value; + if (expr is Constant){ + bool take = !((Constant) expr).IsDefaultValue; if (take){ if (!TrueStatement.Resolve (ec)) @@ -296,15 +302,34 @@ namespace Mono.CSharp { Label end; // - // If we're a boolean expression, Resolve() already + // If we're a boolean constant, Resolve() already // eliminated dead code for us. // - if (expr is BoolConstant){ - bool take = ((BoolConstant) expr).Value; + if (expr is Constant){ + + // + // Simple bool constant + // + if (expr is BoolConstant) { + bool take = ((BoolConstant) expr).Value; + + if (take) + TrueStatement.Emit (ec); + else if (FalseStatement != null) + FalseStatement.Emit (ec); + + return; + } - if (take) + // + // Bool constant with side-effects + // + expr.Emit (ec); + ig.Emit (OpCodes.Pop); + + if (TrueStatement != null) TrueStatement.Emit (ec); - else if (FalseStatement != null) + if (FalseStatement != null) FalseStatement.Emit (ec); return; @@ -349,9 +374,9 @@ namespace Mono.CSharp { public Statement EmbeddedStatement; bool infinite; - public Do (Statement statement, Expression boolExpr, Location l) + public Do (Statement statement, Expression bool_expr, Location l) { - expr = boolExpr; + expr = bool_expr; EmbeddedStatement = statement; loc = l; } @@ -434,9 +459,9 @@ namespace Mono.CSharp { public Statement Statement; bool infinite, empty; - public While (Expression boolExpr, Statement statement, Location l) + public While (Expression bool_expr, Statement statement, Location l) { - this.expr = boolExpr; + this.expr = bool_expr; Statement = statement; loc = l; } @@ -515,6 +540,7 @@ namespace Mono.CSharp { Statement.Emit (ec); ig.MarkLabel (ec.LoopBegin); + ec.Mark (loc, true); expr.EmitBranchable (ec, while_loop, true); @@ -525,6 +551,11 @@ namespace Mono.CSharp { ec.LoopEnd = old_end; } + public override void Emit (EmitContext ec) + { + DoEmit (ec); + } + protected override void CloneTo (CloneContext clonectx, Statement t) { While target = (While) t; @@ -541,13 +572,13 @@ namespace Mono.CSharp { public Statement Statement; bool infinite, empty; - public For (Statement initStatement, + public For (Statement init_statement, Expression test, Statement increment, Statement statement, Location l) { - InitStatement = initStatement; + InitStatement = init_statement; Test = test; Increment = increment; Statement = statement; @@ -714,7 +745,7 @@ namespace Mono.CSharp { /// Implements the return statement /// public class Return : Statement { - Expression Expr; + protected Expression Expr; bool unwind_protect; public Return (Expression expr, Location l) @@ -753,6 +784,12 @@ namespace Mono.CSharp { if (Expr.Type != ec.ReturnType) { if (ec.InferReturnType) { + // + // void cannot be used in contextual return + // + if (Expr.Type == TypeManager.void_type) + return false; + ec.ReturnType = Expr.Type; } else { Expr = Convert.ImplicitConversionRequired ( @@ -1089,7 +1126,8 @@ namespace Mono.CSharp { { Throw target = (Throw) t; - target.expr = expr.Clone (clonectx); + if (expr != null) + target.expr = expr.Clone (clonectx); } } @@ -1255,7 +1293,7 @@ namespace Mono.CSharp { public void EmitSymbolInfo (EmitContext ec, string name) { if (builder != null) - ec.DefineLocalVariable (name, builder); + ec.DefineLocalVariable (Name, builder); } public bool IsThisAssigned (EmitContext ec) @@ -1509,7 +1547,7 @@ namespace Mono.CSharp { // // Labels. (label, block) pairs. // - Hashtable labels; + HybridDictionary labels; // // Keeps track of (name, type) pairs @@ -1518,7 +1556,7 @@ namespace Mono.CSharp { // // Keeps track of constants - Hashtable constants; + HybridDictionary constants; // // Temporary variables. @@ -1530,7 +1568,9 @@ namespace Mono.CSharp { // Block switch_block; + // TODO: merge with scope_initializers ExpressionStatement scope_init; + ArrayList scope_initializers; ArrayList anonymous_children; @@ -1571,7 +1611,7 @@ namespace Mono.CSharp { this.EndLocation = end; this.loc = start; this_id = id++; - statements = new ArrayList (); + statements = new ArrayList (4); } public Block CreateSwitchBlock (Location start) @@ -1597,7 +1637,7 @@ namespace Mono.CSharp { void AddChild (Block b) { if (children == null) - children = new ArrayList (); + children = new ArrayList (1); children.Add (b); } @@ -1668,7 +1708,7 @@ namespace Mono.CSharp { Toplevel.CheckError158 (name, target.loc); if (labels == null) - labels = new Hashtable (); + labels = new HybridDictionary(); labels.Add (name, target); return true; @@ -1843,7 +1883,7 @@ namespace Mono.CSharp { return false; if (constants == null) - constants = new Hashtable (); + constants = new HybridDictionary(); constants.Add (name, value); @@ -1899,6 +1939,18 @@ namespace Mono.CSharp { } return null; } + + // + // It should be used by expressions which require to + // register a statement during resolve process. + // + public void AddScopeStatement (StatementExpression s) + { + if (scope_initializers == null) + scope_initializers = new ArrayList (); + + scope_initializers.Add (s); + } public void AddStatement (Statement s) { @@ -1973,8 +2025,12 @@ namespace Mono.CSharp { LocalInfo vi = (LocalInfo) de.Value; Type variable_type = vi.VariableType; - if (variable_type == null) + if (variable_type == null) { + if (vi.Type is VarExpr) + Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant"); + continue; + } Expression cv = (Expression) constants [name]; if (cv == null) @@ -2064,13 +2120,13 @@ namespace Mono.CSharp { } if (temporary_variables != null) { - foreach (LocalInfo vi in temporary_variables) - vi.ResolveVariable (ec); + for (int i = 0; i < temporary_variables.Count; i++) + ((LocalInfo)temporary_variables[i]).ResolveVariable(ec); } if (children != null){ - foreach (Block b in children) - b.EmitMeta (ec); + for (int i = 0; i < children.Count; i++) + ((Block)children[i]).EmitMeta(ec); } } @@ -2179,10 +2235,10 @@ namespace Mono.CSharp { // if (!s.Resolve (ec)) { + ok = false; if (ec.IsInProbingMode) - return false; + break; - ok = false; statements [ix] = EmptyStatement.Value; continue; } @@ -2200,9 +2256,6 @@ namespace Mono.CSharp { Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation, ec.CurrentBranching, statement_count, num_statements); - if (!ok) - return false; - while (ec.CurrentBranching is FlowBranchingLabeled) ec.EndFlowBranching (); @@ -2263,34 +2316,58 @@ namespace Mono.CSharp { ec.CurrentBlock = this; - bool emit_debug_info = (CodeGen.SymbolWriter != null); - bool is_lexical_block = this == Explicit && Parent != null; + bool emit_debug_info = SymbolWriter.HasSymbolWriter; + bool is_lexical_block = (this == Explicit) && (Parent != null) && + ((flags & Flags.IsIterator) == 0); + + bool omit_debug_info = ec.OmitDebuggingInfo; if (emit_debug_info) { if (is_lexical_block) ec.BeginScope (); } - ec.Mark (StartLocation, true); - if (scope_init != null) + + if ((scope_init != null) || (scope_initializers != null)) + SymbolWriter.OpenCompilerGeneratedBlock (ec.ig); + + if (scope_init != null) { + ec.OmitDebuggingInfo = true; scope_init.EmitStatement (ec); + ec.OmitDebuggingInfo = omit_debug_info; + } + if (scope_initializers != null) { + ec.OmitDebuggingInfo = true; + foreach (StatementExpression s in scope_initializers) + s.Emit (ec); + ec.OmitDebuggingInfo = omit_debug_info; + } + + if ((scope_init != null) || (scope_initializers != null)) + SymbolWriter.CloseCompilerGeneratedBlock (ec.ig); + + ec.Mark (StartLocation, true); DoEmit (ec); - ec.Mark (EndLocation, true); if (emit_debug_info) { + EmitSymbolInfo (ec); + if (is_lexical_block) ec.EndScope (); + } - if (variables != null) { - foreach (DictionaryEntry de in variables) { - string name = (string) de.Key; - LocalInfo vi = (LocalInfo) de.Value; + ec.CurrentBlock = prev_block; + } - vi.EmitSymbolInfo (ec, name); - } + protected virtual void EmitSymbolInfo (EmitContext ec) + { + if (variables != null) { + foreach (DictionaryEntry de in variables) { + string name = (string) de.Key; + LocalInfo vi = (LocalInfo) de.Value; + + vi.EmitSymbolInfo (ec, name); } } - - ec.CurrentBlock = prev_block; } public override string ToString () @@ -2348,7 +2425,11 @@ namespace Mono.CSharp { this.Explicit = this; } - Hashtable known_variables; + public bool IsIterator { + get { return (flags & Flags.IsIterator) != 0; } + } + + HybridDictionary known_variables; // // Marks a variable with name @name as being used in this or a child block. @@ -2358,7 +2439,7 @@ namespace Mono.CSharp { internal void AddKnownVariable (string name, IKnownVariable info) { if (known_variables == null) - known_variables = new Hashtable (); + known_variables = new HybridDictionary(); known_variables [name] = info; @@ -2422,10 +2503,6 @@ namespace Mono.CSharp { set { flags |= Flags.HasVarargs; } } - public bool IsIterator { - get { return (flags & Flags.IsIterator) != 0; } - } - // // The parameters for the block. // @@ -2605,6 +2682,11 @@ namespace Mono.CSharp { return root_scope; } + public override Expression CreateExpressionTree (EmitContext ec) + { + return ((Statement) statements [0]).CreateExpressionTree (ec); + } + public void CreateIteratorHost (RootScopeInfo root) { Report.Debug (64, "CREATE ITERATOR HOST", this, root, Parent, root_scope); @@ -2668,27 +2750,6 @@ namespace Mono.CSharp { return null; } - // - // Whether the parameter named `name' is local to this block, - // or false, if the parameter belongs to an encompassing block. - // - public bool IsLocalParameter (string name) - { - return Parameters.GetParameterByName (name) != null; - } - - // - // Whether the `name' is a parameter reference - // - public bool IsParameterReference (string name) - { - for (ToplevelBlock t = this; t != null; t = t.Container) { - if (t.IsLocalParameter (name)) - return true; - } - return false; - } - LocalInfo this_variable = null; // @@ -2786,15 +2847,27 @@ namespace Mono.CSharp { public override void EmitMeta (EmitContext ec) { + // Avoid declaring an IL variable for this_variable since it is not accessed + // from the generated IL + if (this_variable != null) + Variables.Remove ("this"); base.EmitMeta (ec); parameters.ResolveVariable (this); } + protected override void EmitSymbolInfo (EmitContext ec) + { + if ((AnonymousContainer != null) && (AnonymousContainer.Scope != null)) + SymbolWriter.DefineScopeVariable (AnonymousContainer.Scope.ID); + + base.EmitSymbolInfo (ec); + } + public void MakeIterator (Iterator iterator) { flags |= Flags.IsIterator; - Block block = new ExplicitBlock (this, StartLocation, EndLocation); + Block block = new ExplicitBlock (this, flags, StartLocation, EndLocation); foreach (Statement stmt in statements) block.AddStatement (stmt); statements.Clear (); @@ -2908,7 +2981,7 @@ namespace Mono.CSharp { converted = NullStringCase; return true; } - + c = c.ImplicitConversionRequired (required_type, loc); if (c == null) return false; @@ -2917,19 +2990,19 @@ namespace Mono.CSharp { return true; } - public void Erorr_AlreadyOccurs (Type switchType, SwitchLabel collisionWith) + public void Error_AlreadyOccurs (Type switch_type, SwitchLabel collision_with) { string label; if (converted == null) label = "default"; else if (converted == NullStringCase) label = "null"; - else if (TypeManager.IsEnumType (switchType)) - label = TypeManager.CSharpEnumValue (switchType, converted); + else if (TypeManager.IsEnumType (switch_type)) + label = TypeManager.CSharpEnumValue (switch_type, converted); else label = converted.ToString (); - Report.SymbolRelatedToPreviousError (collisionWith.loc, null); + Report.SymbolRelatedToPreviousError (collision_with.loc, null); Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label); } @@ -3033,7 +3106,7 @@ namespace Mono.CSharp { // Expression SwitchGoverningType (EmitContext ec, Expression expr) { - Type t = TypeManager.DropGenericTypeArguments (expr.Type); + Type t = expr.Type; if (t == TypeManager.byte_type || t == TypeManager.sbyte_type || @@ -3046,7 +3119,7 @@ namespace Mono.CSharp { t == TypeManager.char_type || t == TypeManager.string_type || t == TypeManager.bool_type || - t.IsSubclassOf (TypeManager.enum_type)) + TypeManager.IsEnumType (t)) return expr; if (allowed_types == null){ @@ -3117,7 +3190,7 @@ namespace Mono.CSharp { foreach (SwitchLabel sl in ss.Labels){ if (sl.Label == null){ if (default_section != null){ - sl.Erorr_AlreadyOccurs (SwitchType, (SwitchLabel)default_section.Labels [0]); + sl.Error_AlreadyOccurs (SwitchType, (SwitchLabel)default_section.Labels [0]); error = true; } default_section = ss; @@ -3133,7 +3206,7 @@ namespace Mono.CSharp { try { Elements.Add (key, sl); } catch (ArgumentException) { - sl.Erorr_AlreadyOccurs (SwitchType, (SwitchLabel)Elements [key]); + sl.Error_AlreadyOccurs (SwitchType, (SwitchLabel)Elements [key]); error = true; } } @@ -3192,22 +3265,22 @@ namespace Mono.CSharp { // structure used to hold blocks of keys while calculating table switch class KeyBlock : IComparable { - public KeyBlock (long _nFirst) + public KeyBlock (long _first) { - nFirst = nLast = _nFirst; + first = last = _first; } - public long nFirst; - public long nLast; - public ArrayList rgKeys = null; + public long first; + public long last; + public ArrayList element_keys = null; // how many items are in the bucket public int Size = 1; public int Length { - get { return (int) (nLast - nFirst + 1); } + get { return (int) (last - first + 1); } } - public static long TotalLength (KeyBlock kbFirst, KeyBlock kbLast) + public static long TotalLength (KeyBlock kb_first, KeyBlock kb_last) { - return kbLast.nLast - kbFirst.nFirst + 1; + return kb_last.last - kb_first.first + 1; } public int CompareTo (object obj) { @@ -3215,7 +3288,7 @@ namespace Mono.CSharp { int nLength = Length; int nLengthOther = kb.Length; if (nLengthOther == nLength) - return (int) (kb.nFirst - nFirst); + return (int) (kb.first - first); return nLength - nLengthOther; } } @@ -3232,89 +3305,89 @@ namespace Mono.CSharp { /// void TableSwitchEmit (EmitContext ec, LocalBuilder val) { - int cElements = Elements.Count; - object [] rgKeys = new object [cElements]; - Elements.Keys.CopyTo (rgKeys, 0); - Array.Sort (rgKeys); + int element_count = Elements.Count; + object [] element_keys = new object [element_count]; + Elements.Keys.CopyTo (element_keys, 0); + Array.Sort (element_keys); // initialize the block list with one element per key - ArrayList rgKeyBlocks = new ArrayList (); - foreach (object key in rgKeys) - rgKeyBlocks.Add (new KeyBlock (System.Convert.ToInt64 (key))); + ArrayList key_blocks = new ArrayList (); + foreach (object key in element_keys) + key_blocks.Add (new KeyBlock (System.Convert.ToInt64 (key))); - KeyBlock kbCurr; + KeyBlock current_kb; // iteratively merge the blocks while they are at least half full // there's probably a really cool way to do this with a tree... - while (rgKeyBlocks.Count > 1) + while (key_blocks.Count > 1) { - ArrayList rgKeyBlocksNew = new ArrayList (); - kbCurr = (KeyBlock) rgKeyBlocks [0]; - for (int ikb = 1; ikb < rgKeyBlocks.Count; ikb++) + ArrayList key_blocks_new = new ArrayList (); + current_kb = (KeyBlock) key_blocks [0]; + for (int ikb = 1; ikb < key_blocks.Count; ikb++) { - KeyBlock kb = (KeyBlock) rgKeyBlocks [ikb]; - if ((kbCurr.Size + kb.Size) * 2 >= KeyBlock.TotalLength (kbCurr, kb)) + KeyBlock kb = (KeyBlock) key_blocks [ikb]; + if ((current_kb.Size + kb.Size) * 2 >= KeyBlock.TotalLength (current_kb, kb)) { // merge blocks - kbCurr.nLast = kb.nLast; - kbCurr.Size += kb.Size; + current_kb.last = kb.last; + current_kb.Size += kb.Size; } else { // start a new block - rgKeyBlocksNew.Add (kbCurr); - kbCurr = kb; + key_blocks_new.Add (current_kb); + current_kb = kb; } } - rgKeyBlocksNew.Add (kbCurr); - if (rgKeyBlocks.Count == rgKeyBlocksNew.Count) + key_blocks_new.Add (current_kb); + if (key_blocks.Count == key_blocks_new.Count) break; - rgKeyBlocks = rgKeyBlocksNew; + key_blocks = key_blocks_new; } // initialize the key lists - foreach (KeyBlock kb in rgKeyBlocks) - kb.rgKeys = new ArrayList (); + foreach (KeyBlock kb in key_blocks) + kb.element_keys = new ArrayList (); // fill the key lists int iBlockCurr = 0; - if (rgKeyBlocks.Count > 0) { - kbCurr = (KeyBlock) rgKeyBlocks [0]; - foreach (object key in rgKeys) + if (key_blocks.Count > 0) { + current_kb = (KeyBlock) key_blocks [0]; + foreach (object key in element_keys) { - bool fNextBlock = (key is UInt64) ? (ulong) key > (ulong) kbCurr.nLast : - System.Convert.ToInt64 (key) > kbCurr.nLast; - if (fNextBlock) - kbCurr = (KeyBlock) rgKeyBlocks [++iBlockCurr]; - kbCurr.rgKeys.Add (key); + bool next_block = (key is UInt64) ? (ulong) key > (ulong) current_kb.last : + System.Convert.ToInt64 (key) > current_kb.last; + if (next_block) + current_kb = (KeyBlock) key_blocks [++iBlockCurr]; + current_kb.element_keys.Add (key); } } // sort the blocks so we can tackle the largest ones first - rgKeyBlocks.Sort (); + key_blocks.Sort (); // okay now we can start... ILGenerator ig = ec.ig; - Label lblEnd = ig.DefineLabel (); // at the end ;-) - Label lblDefault = ig.DefineLabel (); + Label lbl_end = ig.DefineLabel (); // at the end ;-) + Label lbl_default = ig.DefineLabel (); - Type typeKeys = null; - if (rgKeys.Length > 0) - typeKeys = rgKeys [0].GetType (); // used for conversions + Type type_keys = null; + if (element_keys.Length > 0) + type_keys = element_keys [0].GetType (); // used for conversions Type compare_type; if (TypeManager.IsEnumType (SwitchType)) - compare_type = TypeManager.EnumToUnderlying (SwitchType); + compare_type = TypeManager.GetEnumUnderlyingType (SwitchType); else compare_type = SwitchType; - for (int iBlock = rgKeyBlocks.Count - 1; iBlock >= 0; --iBlock) + for (int iBlock = key_blocks.Count - 1; iBlock >= 0; --iBlock) { - KeyBlock kb = ((KeyBlock) rgKeyBlocks [iBlock]); - lblDefault = (iBlock == 0) ? DefaultTarget : ig.DefineLabel (); + KeyBlock kb = ((KeyBlock) key_blocks [iBlock]); + lbl_default = (iBlock == 0) ? DefaultTarget : ig.DefineLabel (); if (kb.Length <= 2) { - foreach (object key in kb.rgKeys) + foreach (object key in kb.element_keys) { ig.Emit (OpCodes.Ldloc, val); EmitObjectInteger (ig, key); @@ -3333,17 +3406,17 @@ namespace Mono.CSharp { // check block range (could be > 2^31) ig.Emit (OpCodes.Ldloc, val); - EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys)); - ig.Emit (OpCodes.Blt, lblDefault); + EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys)); + ig.Emit (OpCodes.Blt, lbl_default); ig.Emit (OpCodes.Ldloc, val); - EmitObjectInteger (ig, System.Convert.ChangeType (kb.nLast, typeKeys)); - ig.Emit (OpCodes.Bgt, lblDefault); + EmitObjectInteger (ig, System.Convert.ChangeType (kb.last, type_keys)); + ig.Emit (OpCodes.Bgt, lbl_default); // normalize range ig.Emit (OpCodes.Ldloc, val); - if (kb.nFirst != 0) + if (kb.first != 0) { - EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys)); + EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys)); ig.Emit (OpCodes.Sub); } ig.Emit (OpCodes.Conv_I4); // assumes < 2^31 labels! @@ -3352,15 +3425,15 @@ namespace Mono.CSharp { { // normalize range ig.Emit (OpCodes.Ldloc, val); - int nFirst = (int) kb.nFirst; - if (nFirst > 0) + int first = (int) kb.first; + if (first > 0) { - IntConstant.EmitInt (ig, nFirst); + IntConstant.EmitInt (ig, first); ig.Emit (OpCodes.Sub); } - else if (nFirst < 0) + else if (first < 0) { - IntConstant.EmitInt (ig, -nFirst); + IntConstant.EmitInt (ig, -first); ig.Emit (OpCodes.Add); } } @@ -3368,26 +3441,26 @@ namespace Mono.CSharp { // first, build the list of labels for the switch int iKey = 0; int cJumps = kb.Length; - Label [] rgLabels = new Label [cJumps]; + Label [] switch_labels = new Label [cJumps]; for (int iJump = 0; iJump < cJumps; iJump++) { - object key = kb.rgKeys [iKey]; - if (System.Convert.ToInt64 (key) == kb.nFirst + iJump) + object key = kb.element_keys [iKey]; + if (System.Convert.ToInt64 (key) == kb.first + iJump) { SwitchLabel sl = (SwitchLabel) Elements [key]; - rgLabels [iJump] = sl.GetILLabel (ec); + switch_labels [iJump] = sl.GetILLabel (ec); iKey++; } else - rgLabels [iJump] = lblDefault; + switch_labels [iJump] = lbl_default; } // emit the switch opcode - ig.Emit (OpCodes.Switch, rgLabels); + ig.Emit (OpCodes.Switch, switch_labels); } // mark the default for this block if (iBlock != 0) - ig.MarkLabel (lblDefault); + ig.MarkLabel (lbl_default); } // TODO: find the default case and emit it here, @@ -3395,16 +3468,16 @@ namespace Mono.CSharp { // make sure to mark other labels in the default section // the last default just goes to the end - ig.Emit (OpCodes.Br, lblDefault); + ig.Emit (OpCodes.Br, lbl_default); // now emit the code for the sections - bool fFoundDefault = false; - bool fFoundNull = false; + bool found_default = false; + bool found_null = false; foreach (SwitchSection ss in Sections) { foreach (SwitchLabel sl in ss.Labels) if (sl.Converted == SwitchLabel.NullStringCase) - fFoundNull = true; + found_null = true; } foreach (SwitchSection ss in Sections) @@ -3416,23 +3489,23 @@ namespace Mono.CSharp { if (sl.Converted == SwitchLabel.NullStringCase) ig.MarkLabel (null_target); else if (sl.Label == null) { - ig.MarkLabel (lblDefault); - fFoundDefault = true; - if (!fFoundNull) + ig.MarkLabel (lbl_default); + found_default = true; + if (!found_null) ig.MarkLabel (null_target); } } ss.Block.Emit (ec); } - if (!fFoundDefault) { - ig.MarkLabel (lblDefault); - if (HaveUnwrap && !fFoundNull) { + if (!found_default) { + ig.MarkLabel (lbl_default); + if (HaveUnwrap && !found_null) { ig.MarkLabel (null_target); } } - ig.MarkLabel (lblEnd); + ig.MarkLabel (lbl_end); } // // This simple emit switch works, but does not take advantage of the @@ -3574,7 +3647,7 @@ namespace Mono.CSharp { SwitchType = new_expr.Type; if (RootContext.Version == LanguageVersion.ISO_1 && SwitchType == TypeManager.bool_type) { - Report.FeatureIsNotISO1 (loc, "switch expression of boolean type"); + Report.FeatureIsNotAvailable (loc, "switch expression of boolean type"); return false; } @@ -3602,6 +3675,7 @@ namespace Mono.CSharp { } bool first = true; + bool ok = true; foreach (SwitchSection ss in Sections){ if (!first) ec.CurrentBranching.CreateSibling ( @@ -3614,11 +3688,12 @@ namespace Mono.CSharp { // one single section - mark all the others as // unreachable. ec.CurrentBranching.CurrentUsageVector.Goto (); - if (!ss.Block.ResolveUnreachable (ec, true)) - return false; + if (!ss.Block.ResolveUnreachable (ec, true)) { + ok = false; + } } else { if (!ss.Block.Resolve (ec)) - return false; + ok = false; } } @@ -3631,7 +3706,12 @@ namespace Mono.CSharp { Report.Debug (1, "END OF SWITCH BLOCK", loc, ec.CurrentBranching); - return true; + if (TypeManager.string_isinterned_string == null) { + TypeManager.string_isinterned_string = TypeManager.GetPredefinedMethod (TypeManager.string_type, + "IsInterned", loc, TypeManager.string_type); + } + + return ok; } protected override void DoEmit (EmitContext ec) @@ -3766,6 +3846,14 @@ namespace Mono.CSharp { temp = new TemporaryVariable (t, loc); temp.Resolve (ec); + + if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) { + Type monitor_type = TypeManager.CoreLookupType ("System.Threading", "Monitor", Kind.Class, true); + TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod ( + monitor_type, "Enter", loc, TypeManager.object_type); + TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod ( + monitor_type, "Exit", loc, TypeManager.object_type); + } return ok; } @@ -3993,9 +4081,13 @@ namespace Mono.CSharp { return false; } - TypeExpr texpr = type.ResolveAsTypeTerminal (ec, false); - if (texpr == null) + TypeExpr texpr = type.ResolveAsContextualType (ec, false); + if (texpr == null) { + if (type is VarExpr) + Report.Error (821, type.Location, "A fixed statement cannot use an implicitly typed local variable"); + return false; + } expr_type = texpr.Type; @@ -4100,7 +4192,7 @@ namespace Mono.CSharp { // fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0]) // converted = new Conditional (new Binary (Binary.Operator.LogicalOr, - new Binary (Binary.Operator.Equality, e, new NullConstant (loc)), + new Binary (Binary.Operator.Equality, e, new NullLiteral (loc)), new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc))), NullPointer.Null, converted); @@ -4259,7 +4351,7 @@ namespace Mono.CSharp { type = te.Type; - if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){ + if (type != TypeManager.exception_type && !TypeManager.IsSubclassOf (type, TypeManager.exception_type)){ Error (155, "The type caught or thrown must be derived from System.Exception"); return false; } @@ -4328,7 +4420,7 @@ namespace Mono.CSharp { Report.Debug (1, "START OF CATCH BLOCKS", vector); - Type[] prevCatches = new Type [Specific.Count]; + Type[] prev_catches = new Type [Specific.Count]; int last_index = 0; foreach (Catch c in Specific){ ec.CurrentBranching.CreateSibling ( @@ -4347,15 +4439,15 @@ namespace Mono.CSharp { if (!c.Resolve (ec)) return false; - Type resolvedType = c.CatchType; + Type resolved_type = c.CatchType; for (int ii = 0; ii < last_index; ++ii) { - if (resolvedType == prevCatches [ii] || resolvedType.IsSubclassOf (prevCatches [ii])) { - Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type `{0}'", prevCatches [ii].FullName); + if (resolved_type == prev_catches [ii] || TypeManager.IsSubclassOf (resolved_type, prev_catches [ii])) { + Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type `{0}'", prev_catches [ii].FullName); return false; } } - prevCatches [last_index++] = resolvedType; + prev_catches [last_index++] = resolved_type; need_exc_block = true; } @@ -4721,6 +4813,11 @@ namespace Mono.CSharp { // So, ensure there's some IL code after the finally block. ec.NeedReturnLabel (); + if (TypeManager.void_dispose_void == null) { + TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod ( + TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes); + } + return ok; } @@ -4744,10 +4841,22 @@ namespace Mono.CSharp { { Using target = (Using) t; - if (expression_or_block is Expression) + if (expression_or_block is Expression) { target.expression_or_block = ((Expression) expression_or_block).Clone (clonectx); - else - target.expression_or_block = ((Statement) expression_or_block).Clone (clonectx); + } else { + DictionaryEntry de = (DictionaryEntry) expression_or_block; + ArrayList var_list = (ArrayList) de.Value; + ArrayList target_var_list = new ArrayList (var_list.Count); + + foreach (DictionaryEntry de_variable in var_list) + target_var_list.Add (new DictionaryEntry ( + ((Expression) de_variable.Key).Clone (clonectx), + ((Expression) de_variable.Value).Clone (clonectx))); + + target.expression_or_block = new DictionaryEntry ( + ((Expression) de.Key).Clone (clonectx), + target_var_list); + } target.Statement = Statement.Clone (clonectx); } @@ -4784,7 +4893,7 @@ namespace Mono.CSharp { if (expr == null) return false; - if (expr.Type == TypeManager.null_type) { + if (expr.IsNull) { Report.Error (186, loc, "Use of null is not valid in this context"); return false; } @@ -5048,6 +5157,16 @@ namespace Mono.CSharp { // way I could do this without a goto // + if (TypeManager.bool_movenext_void == null) { + TypeManager.bool_movenext_void = TypeManager.GetPredefinedMethod ( + TypeManager.ienumerator_type, "MoveNext", loc, Type.EmptyTypes); + } + + if (TypeManager.ienumerator_getcurrent == null) { + TypeManager.ienumerator_getcurrent = TypeManager.GetPredefinedProperty ( + TypeManager.ienumerator_type, "Current", loc, TypeManager.object_type); + } + #if GMCS_SOURCE // // Prefer a generic enumerator over a non-generic one. @@ -5349,6 +5468,11 @@ namespace Mono.CSharp { if (is_disposable) { ResolveFinally (branching); ec.EndFlowBranching (); + + if (TypeManager.void_dispose_void == null) { + TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod ( + TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes); + } } else emit_finally = true;