Kaynağa Gözat

2001-11-16 Miguel de Icaza <[email protected]>

	* statement.cs: Implement foreach on multi-dimensional arrays.

	* parameter.cs (Parameters.GetParameterByName): Also lookup the
	name of the params argument.

	* expression.cs: Use EmitStoreOpcode to get the right opcode while
	initializing the array.

	(ArrayAccess.EmitStoreOpcode): move the opcode generation here, so
	we can use this elsewhere.

	* statement.cs: Finish implementation of foreach for single
	dimension arrays.

	* cs-parser.jay: Use an out-of-band stack to pass information
	around, I wonder why I need this.

	foreach_block: Make the new foreach_block the current_block.

	* parameter.cs (Parameters.GetEmptyReadOnlyParameters): New
	function used to return a static Parameters structure.  Used for
	empty parameters, as those are created very frequently.

	* cs-parser.jay, class.cs: Use GetEmptyReadOnlyParameters

2001-11-16  Miguel de Icaza  <[email protected]>

	* test-34.cs: Improve this test to check if we are actually
	walking over the arguments in foreach.

svn path=/trunk/mcs/; revision=1371
Miguel de Icaza 24 yıl önce
ebeveyn
işleme
fea2d810c8

+ 9 - 0
mcs/errors/cs0136-2.cs

@@ -0,0 +1,9 @@
+// cs0136.cs: local variable j can not be declared, because there is something with that name already
+// Line: 5
+class X {
+	public static void Bar (int j, params int [] args)
+	{
+		foreach (int j in args)
+			;
+	}
+}

+ 27 - 0
mcs/mcs/ChangeLog

@@ -1,3 +1,30 @@
+2001-11-16  Miguel de Icaza  <[email protected]>
+
+	* statement.cs: Implement foreach on multi-dimensional arrays. 
+
+	* parameter.cs (Parameters.GetParameterByName): Also lookup the
+	name of the params argument.
+
+	* expression.cs: Use EmitStoreOpcode to get the right opcode while
+	initializing the array.
+
+	(ArrayAccess.EmitStoreOpcode): move the opcode generation here, so
+	we can use this elsewhere.
+
+	* statement.cs: Finish implementation of foreach for single
+	dimension arrays.
+
+	* cs-parser.jay: Use an out-of-band stack to pass information
+	around, I wonder why I need this.
+
+	foreach_block: Make the new foreach_block the current_block.
+
+	* parameter.cs (Parameters.GetEmptyReadOnlyParameters): New
+	function used to return a static Parameters structure.  Used for
+	empty parameters, as those are created very frequently.
+
+	* cs-parser.jay, class.cs: Use GetEmptyReadOnlyParameters
+
 2001-11-15  Ravi Pratap  <[email protected]>
 
 	* interface.cs : Default modifier is private, not public. The

+ 14 - 0
mcs/mcs/TODO

@@ -138,6 +138,20 @@ BUGS
 
 	Multi-dim arrays are declared as [,] instead of [0..,0..]
 
+* Variables
+
+	Things like:
+
+	for (int i = 0; ...; i++){
+	}
+
+	for (int i = 0; i < 10; i++){
+	}
+
+	Currently defines `i' for the rest of the execution after the first
+	loop, so the second loop generates an error.
+
+	I think we should pop all the blocks until this point.
 
 PENDING TASKS
 -------------

+ 0 - 1
mcs/mcs/attribute.cs

@@ -392,6 +392,5 @@ namespace CIR {
 			if (a != null)
 				AttributeSections.Add (a);
 		}
-		
 	}
 }

+ 72 - 61
mcs/mcs/class.cs

@@ -544,7 +544,7 @@ namespace CIR {
 			Constructor c;
 			int mods = 0;
 
-			c = new Constructor (Basename, new Parameters (null, null),
+			c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
 					     new ConstructorBaseInitializer (null, new Location (-1)),
 					     new Location (-1));
 			
@@ -1357,29 +1357,30 @@ namespace CIR {
 				
 				if (OptAttributes.AttributeSections != null) {
 					foreach (AttributeSection asec in OptAttributes.AttributeSections) {
-						if (asec.Attributes != null) {
-							foreach (Attribute a in asec.Attributes) {
-								CustomAttributeBuilder cb = a.Resolve (ec);
-								if (cb == null)
-									continue;
-
-								if (a.UsageAttr) {
-									this.Targets = a.Targets;
-									this.AllowMultiple = a.AllowMultiple;
-									this.Inherited = a.Inherited;
-
-									RootContext.TypeManager.RegisterAttrType (
-										           TypeBuilder, this);
-								} else {
-
-									if (!Attribute.CheckAttribute (a, this)) {
-										Attribute.Error592 (a, Location);
-										return;
-									}
-								}
+						if (asec.Attributes == null)
+							continue;
+						
+						foreach (Attribute a in asec.Attributes) {
+							CustomAttributeBuilder cb = a.Resolve (ec);
+							if (cb == null)
+								continue;
+							
+							if (a.UsageAttr) {
+								this.Targets = a.Targets;
+								this.AllowMultiple = a.AllowMultiple;
+								this.Inherited = a.Inherited;
+								
+								RootContext.TypeManager.RegisterAttrType (
+									TypeBuilder, this);
+							} else {
 								
-								TypeBuilder.SetCustomAttribute (cb);
+								if (!Attribute.CheckAttribute (a, this)) {
+									Attribute.Error592 (a, Location);
+									return;
+								}
 							}
+							
+							TypeBuilder.SetCustomAttribute (cb);
 						}
 					}
 				}
@@ -1853,6 +1854,12 @@ namespace CIR {
 			if (Name == "Main"){
 				if ((ModFlags & Modifiers.STATIC) != 0){
 					parent.RootContext.EntryPoint = MethodBuilder;
+
+					//
+					// FIXME: Verify that the method signature
+					// is valid for an entry point, and report
+					// error 28 if not.
+					//
 				}
 			}
 			
@@ -2098,19 +2105,20 @@ namespace CIR {
 			if (OptAttributes != null) {
 				if (OptAttributes.AttributeSections != null) {
 					foreach (AttributeSection asec in OptAttributes.AttributeSections) {
-						if (asec.Attributes != null) {
-							foreach (Attribute a in asec.Attributes) {
-								CustomAttributeBuilder cb = a.Resolve (ec);
-								if (cb == null)
-									continue;
-
-								if (!Attribute.CheckAttribute (a, this)) {
-									Attribute.Error592 (a, Location);
-									return;
-								}
-								
-								ConstructorBuilder.SetCustomAttribute (cb);
+						if (asec.Attributes == null)
+							continue;
+						
+						foreach (Attribute a in asec.Attributes) {
+							CustomAttributeBuilder cb = a.Resolve (ec);
+							if (cb == null)
+								continue;
+							
+							if (!Attribute.CheckAttribute (a, this)) {
+								Attribute.Error592 (a, Location);
+								return;
 							}
+							
+							ConstructorBuilder.SetCustomAttribute (cb);
 						}
 					}
 				}
@@ -2221,7 +2229,7 @@ namespace CIR {
 			Modifiers.OVERRIDE |
 			Modifiers.ABSTRACT |
 			Modifiers.VIRTUAL;
-		
+
 		public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
 				 Attributes attrs, Location loc)
 		{
@@ -2269,7 +2277,8 @@ namespace CIR {
 				}
 
 				TypeContainer.RegisterParameterForBuilder (GetBuilder,
-					      new InternalParameters (parent, new Parameters (null, null)));
+					      new InternalParameters (
+						      parent, Parameters.GetEmptyReadOnlyParameters ()));
 			}
 			
 			if (Set != null)
@@ -2318,6 +2327,7 @@ namespace CIR {
 
 			if (OptAttributes != null) {
 				ec = new EmitContext (tc, null, PropertyType, ModFlags);
+
 				if (OptAttributes.AttributeSections != null) {
 					foreach (AttributeSection asec in OptAttributes.AttributeSections) {
 						if (asec.Attributes == null)
@@ -2629,19 +2639,20 @@ namespace CIR {
 				ec = new EmitContext (tc, null, IndexerType, ModFlags);
 				if (OptAttributes.AttributeSections != null) {
 					foreach (AttributeSection asec in OptAttributes.AttributeSections) {
-						if (asec.Attributes != null) {
-							foreach (Attribute a in asec.Attributes) {
-								CustomAttributeBuilder cb = a.Resolve (ec);
-								if (cb == null)
-									continue;
-
-								if (!Attribute.CheckAttribute (a, this)) {
-									Attribute.Error592 (a, Location);
-									return;
-								}
-
-								PropertyBuilder.SetCustomAttribute (cb);
+						if (asec.Attributes == null)
+							continue;
+						
+						foreach (Attribute a in asec.Attributes) {
+							CustomAttributeBuilder cb = a.Resolve (ec);
+							if (cb == null)
+								continue;
+							
+							if (!Attribute.CheckAttribute (a, this)) {
+								Attribute.Error592 (a, Location);
+								return;
 							}
+							
+							PropertyBuilder.SetCustomAttribute (cb);
 						}
 					}
 				}
@@ -2849,21 +2860,23 @@ namespace CIR {
 		{
 			if (OptAttributes != null) {
 				EmitContext ec = new EmitContext (parent, null, null, ModFlags);
+
 				if (OptAttributes.AttributeSections != null) {
 					foreach (AttributeSection asec in OptAttributes.AttributeSections) {
-						if (asec.Attributes != null) {
-							foreach (Attribute a in asec.Attributes) {
-								CustomAttributeBuilder cb = a.Resolve (ec);
-								if (cb == null)
-									continue;
-
-								if (!Attribute.CheckAttribute (a, this)) {
-									Attribute.Error592 (a, Location);
-									return;
-								}
+						if (asec.Attributes == null)
+							continue;
+						
+						foreach (Attribute a in asec.Attributes) {
+							CustomAttributeBuilder cb = a.Resolve (ec);
+							if (cb == null)
+								continue;
 
-								OperatorMethodBuilder.SetCustomAttribute (cb);
+							if (!Attribute.CheckAttribute (a, this)) {
+								Attribute.Error592 (a, Location);
+								return;
 							}
+							
+							OperatorMethodBuilder.SetCustomAttribute (cb);
 						}
 					}
 				}
@@ -2872,8 +2885,6 @@ namespace CIR {
 			OperatorMethod.Block = Block;
 			OperatorMethod.Emit (parent);
 		}
-		
-
 	}
 
 	//

+ 25 - 9
mcs/mcs/cs-parser.jay

@@ -78,6 +78,11 @@ namespace CIR
 		// </summary>
 		Tree tree;
 
+		//
+		// An out-of-band stack.
+		//
+		Stack oob_stack;
+
 		RootContext rc;
 
 %}
@@ -795,7 +800,7 @@ method_body
 	;
 
 opt_formal_parameter_list
-	: /* empty */			{ $$ = new Parameters (null, null); }
+	: /* empty */			{ $$ = Parameters.GetEmptyReadOnlyParameters (); }
 	| formal_parameter_list
 	;
 
@@ -2780,20 +2785,30 @@ statement_expression_list
 
 foreach_statement
 	: FOREACH OPEN_PARENS type IDENTIFIER IN 
-	  { 
-		// empty
-	  } 
+	  {
+		oob_stack.Push (lexer.Location);
+	  }
 	  expression CLOSE_PARENS 
-	  embedded_statement
 	  {
 		Block foreach_block = new Block (current_block, true);
 		LocalVariableReference v;
 
-		foreach_block.AddVariable ((string) $3, (string) $4, (Location) $1);
+		foreach_block.AddVariable ((string) $3, (string) $4, lexer.Location);
 		v = new LocalVariableReference (foreach_block, (string) $4);
-		foreach_block.AddStatement (new Foreach ((string) $3, v, (Expression) $7, 
-					    (Statement) $9, lexer.Location));
-		$$ = foreach_block;
+
+		current_block.AddStatement (foreach_block);
+		current_block = foreach_block;
+
+		oob_stack.Push (foreach_block);
+		oob_stack.Push (v);
+	  } 
+	  embedded_statement 
+	  {
+		LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
+		Block foreach_block = (Block) oob_stack.Pop ();
+		Location l = (Location) oob_stack.Pop ();
+
+		$$ = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
 	  }
 	;
 
@@ -3362,6 +3377,7 @@ public CSharpParser(RootContext rc, string name, System.IO.Stream input)
 	this.input = input;
 	current_container = tree.Types;
 	current_container.Namespace = current_namespace;
+	oob_stack = new Stack ();
 
 	lexer = new Tokenizer (input, name);
 }

+ 2 - 2
mcs/mcs/driver.cs

@@ -82,12 +82,12 @@ namespace CIR
 				"-v           Verbose parsing\n"+
 				"-o           Specifies output file\n" +
 				"-L           Specifies path for loading assemblies\n" +
-				"--fatal      Makes errors fatal\n" + 
+				"--checked    Set default context to checked\n" +
+				"--fatal      Makes errors fatal\n" +
 				"--nostdlib   Does not load core libraries\n" +
 				"--target     Specifies the target (exe, winexe, library, module)\n" +
 				"--parse      Only parses the source file\n" +
 				"--probe X L  Probes for the source to generate code X on line L\n" +
-				"--checked    Set default context to checked\n" +
 				"-r           References an assembly\n");
 			
 		}

+ 33 - 22
mcs/mcs/expression.cs

@@ -1937,7 +1937,6 @@ namespace CIR {
 
 				return (ParameterData) ip;
 			} else {
-				Console.WriteLine ("Getting parameters for: " + mb);
 				ParameterInfo [] pi = mb.GetParameters ();
 				ReflectionParameters rp = new ReflectionParameters (pi);
 				method_parameter_cache [mb] = rp;
@@ -2601,17 +2600,20 @@ namespace CIR {
 			string array_type = t.FullName + "[]";
 			LocalBuilder array;
 			
-			array = ec.GetTemporaryStorage (Type.GetType (array_type));
+			array = ig.DeclareLocal (Type.GetType (array_type));
 			IntLiteral.EmitInt (ig, count);
 			ig.Emit (OpCodes.Newarr, t);
 			ig.Emit (OpCodes.Stloc, array);
 
 			int top = arguments.Count;
 			for (int j = idx; j < top; j++){
+				a = (Argument) arguments [j];
+				
 				ig.Emit (OpCodes.Ldloc, array);
 				IntLiteral.EmitInt (ig, j - idx);
 				a.Emit (ec);
-				ig.Emit (OpCodes.Stelem_Ref);
+				
+				ArrayAccess.EmitStoreOpcode (ig, t);
 			}
 			ig.Emit (OpCodes.Ldloc, array);
 		}
@@ -2687,7 +2689,7 @@ namespace CIR {
 							Type t = instance_expr.Type;
 							
 							instance_expr.Emit (ec);
-							LocalBuilder temp = ec.GetTemporaryStorage (t);
+							LocalBuilder temp = ig.DeclareLocal (t);
 							ig.Emit (OpCodes.Stloc, temp);
 							ig.Emit (OpCodes.Ldloca, temp);
 						}
@@ -3558,6 +3560,30 @@ namespace CIR {
 			else
 				ig.Emit (OpCodes.Ldelem_Ref);
 		}
+
+		// <summary>
+		//    Emits the right opcode to store an object of Type `t'
+		//    from an array of T.  
+		// </summary>
+		static public void EmitStoreOpcode (ILGenerator ig, Type t)
+		{
+			if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
+				ig.Emit (OpCodes.Stelem_I1);
+			else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
+				ig.Emit (OpCodes.Stelem_I2);
+			else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
+				ig.Emit (OpCodes.Stelem_I4);
+			else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
+				ig.Emit (OpCodes.Stelem_I8);
+			else if (t == TypeManager.float_type)
+				ig.Emit (OpCodes.Stelem_R4);
+			else if (t == TypeManager.double_type)
+				ig.Emit (OpCodes.Stelem_R8);
+			else if (t == TypeManager.intptr_type)
+				ig.Emit (OpCodes.Stelem_I);
+			else
+				ig.Emit (OpCodes.Stelem_Ref);
+		}
 		
 		public override void Emit (EmitContext ec)
 		{
@@ -3604,24 +3630,9 @@ namespace CIR {
 			source.Emit (ec);
 
 			Type t = source.Type;
-			if (rank == 1){
-				if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
-					ig.Emit (OpCodes.Stelem_I1);
-				else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
-					ig.Emit (OpCodes.Stelem_I2);
-				else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
-					ig.Emit (OpCodes.Stelem_I4);
-				else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
-					ig.Emit (OpCodes.Stelem_I8);
-				else if (t == TypeManager.float_type)
-					ig.Emit (OpCodes.Stelem_R4);
-				else if (t == TypeManager.double_type)
-					ig.Emit (OpCodes.Stelem_R8);
-				else if (t == TypeManager.intptr_type)
-					ig.Emit (OpCodes.Stelem_I);
-				else
-					ig.Emit (OpCodes.Stelem_Ref);
-			} else {
+			if (rank == 1)
+				EmitStoreOpcode (ig, t);
+			else {
 				ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
 				Type [] args = new Type [ea.Arguments.Count + 1];
 				MethodInfo set;

+ 21 - 1
mcs/mcs/parameter.cs

@@ -87,9 +87,11 @@ namespace CIR {
 
 	public class Parameters {
 		public Parameter [] FixedParameters;
-		public readonly Parameter    ArrayParameter;
+		public readonly Parameter ArrayParameter;
 		string signature;
 		Type [] types;
+
+		static Parameters empty_parameters;
 		
 		public Parameters (Parameter [] fixed_parameters, Parameter array_parameter)
 		{
@@ -97,6 +99,18 @@ namespace CIR {
 			ArrayParameter  = array_parameter;
 		}
 
+		// <summary>
+		//   This is used to reuse a set of empty parameters, because they
+		//   are common
+		// </summary>
+		public static Parameters GetEmptyReadOnlyParameters ()
+		{
+			if (empty_parameters == null)
+				empty_parameters = new Parameters (null, null);
+			
+			return empty_parameters;
+		}
+		
 		public bool Empty {
 			get {
 				return (FixedParameters == null) && (ArrayParameter == null);
@@ -174,6 +188,12 @@ namespace CIR {
 				i++;
 			}
 
+			if (ArrayParameter != null)
+				if (name == ArrayParameter.Name){
+					idx = i;
+					return ArrayParameter;
+				}
+			
 			return null;
 		}
 

+ 74 - 14
mcs/mcs/statement.cs

@@ -574,13 +574,13 @@ namespace CIR {
 				object temp;
 				temp = variables [name];
 
-				if (temp != null)
+				if (temp != null){
 					return (VariableInfo) temp;
+				}
 			}
 
-			if (Parent != null){
+			if (Parent != null)
 				return Parent.GetVariableInfo (name);
-			}
 
 			return null;
 		}
@@ -847,8 +847,8 @@ namespace CIR {
 				return false;
 			}
 
-			LocalBuilder temp = ec.GetTemporaryStorage (type);
 			ILGenerator ig = ec.ig;
+			LocalBuilder temp = ig.DeclareLocal (type);
 				
 			e.Emit (ec);
 			ig.Emit (OpCodes.Dup);
@@ -1237,19 +1237,19 @@ namespace CIR {
 			int rank = array_type.GetArrayRank ();
 			ILGenerator ig = ec.ig;
 
-			Console.WriteLine ("Rank= " + rank);
+			LocalBuilder copy = ig.DeclareLocal (array_type);
+			
+			//
+			// Make our copy of the array
+			//
+			expr.Emit (ec);
+			ig.Emit (OpCodes.Stloc, copy);
+			
 			if (rank == 1){
-				LocalBuilder counter = ec.GetTemporaryStorage (TypeManager.int32_type);
-				LocalBuilder copy = ec.GetTemporaryStorage (array_type);
+				LocalBuilder counter = ig.DeclareLocal (TypeManager.int32_type);
 
 				Label loop, test;
 				
-				//
-				// Make our copy of the array
-				//
-				expr.Emit (ec);
-				ig.Emit (OpCodes.Stloc, copy);
-				
 				ig.Emit (OpCodes.Ldc_I4_0);
 				ig.Emit (OpCodes.Stloc, counter);
 				test = ig.DefineLabel ();
@@ -1258,6 +1258,8 @@ namespace CIR {
 				loop = ig.DefineLabel ();
 				ig.MarkLabel (loop);
 
+				ig.Emit (OpCodes.Ldloc, copy);
+				ig.Emit (OpCodes.Ldloc, counter);
 				ArrayAccess.EmitLoadOpcode (ig, var_type);
 
 				variable.EmitAssign (ec, conv);
@@ -1276,7 +1278,65 @@ namespace CIR {
 				ig.Emit (OpCodes.Conv_I4);
 				ig.Emit (OpCodes.Blt, loop);
 			} else {
-				throw new Exception ("Unimplemented");
+				LocalBuilder [] dim_len   = new LocalBuilder [rank];
+				LocalBuilder [] dim_count = new LocalBuilder [rank];
+				Label [] loop = new Label [rank];
+				Label [] test = new Label [rank];
+				int dim;
+				
+				for (dim = 0; dim < rank; dim++){
+					dim_len [dim] = ig.DeclareLocal (TypeManager.int32_type);
+					dim_count [dim] = ig.DeclareLocal (TypeManager.int32_type);
+					test [dim] = ig.DefineLabel ();
+					loop [dim] = ig.DefineLabel ();
+				}
+					
+				for (dim = 0; dim < rank; dim++){
+					ig.Emit (OpCodes.Ldloc, copy);
+					IntLiteral.EmitInt (ig, dim);
+					ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
+					ig.Emit (OpCodes.Stloc, dim_len [dim]);
+				}
+
+				for (dim = 0; dim < rank; dim++){
+					ig.Emit (OpCodes.Ldc_I4_0);
+					ig.Emit (OpCodes.Stloc, dim_count [dim]);
+					ig.Emit (OpCodes.Br, test [dim]);
+					ig.MarkLabel (loop [dim]);
+				}
+
+				ig.Emit (OpCodes.Ldloc, copy);
+				for (dim = 0; dim < rank; dim++)
+					ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+
+				//
+				// FIXME: Maybe we can cache the computation of `get'?
+				//
+				Type [] args = new Type [rank];
+				MethodInfo get;
+
+				for (int i = 0; i < rank; i++)
+					args [i] = TypeManager.int32_type;
+
+				ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
+				get = mb.GetArrayMethod (
+					array_type, "Get",
+					CallingConventions.HasThis| CallingConventions.Standard,
+					var_type, args);
+				ig.Emit (OpCodes.Call, get);
+				variable.EmitAssign (ec, conv);
+				statement.Emit (ec);
+				for (dim = rank - 1; dim >= 0; dim--){
+					ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+					ig.Emit (OpCodes.Ldc_I4_1);
+					ig.Emit (OpCodes.Add);
+					ig.Emit (OpCodes.Stloc, dim_count [dim]);
+
+					ig.MarkLabel (test [dim]);
+					ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+					ig.Emit (OpCodes.Ldloc, dim_len [dim]);
+					ig.Emit (OpCodes.Blt, loop [dim]);
+				}
 			}
 
 			return false;

+ 9 - 1
mcs/mcs/typemanager.cs

@@ -72,7 +72,8 @@ public class TypeManager {
 	static public MethodInfo void_monitor_enter_object;
 	static public MethodInfo void_monitor_exit_object;
 	static public MethodInfo void_initializearray_array_fieldhandle;
-
+	static public MethodInfo int_getlength_int;
+	
 	//
 	// The attribute constructors.
 	//
@@ -434,6 +435,13 @@ public class TypeManager {
 		void_initializearray_array_fieldhandle = GetMethod (
 			runtime_helpers_type, "InitializeArray", array_field_handle_arg);
 
+		//
+		// Array functions
+		//
+		Type [] int_arg = { int32_type };
+		int_getlength_int = GetMethod (
+			array_type, "GetLength", int_arg);
+		
 		//
 		// Attributes
 		//

+ 5 - 0
mcs/tests/ChangeLog

@@ -1,3 +1,8 @@
+2001-11-16  Miguel de Icaza  <[email protected]>
+
+	* test-34.cs: Improve this test to check if we are actually
+	walking over the arguments in foreach.
+
 2001-11-15  Ravi Pratap  <[email protected]>
 
 	* makefile : Update to include test-33 again. All tests

+ 2 - 2
mcs/tests/makefile

@@ -8,10 +8,10 @@ TEST_SOURCES = \
 	test-1  test-2  test-3  test-4  test-5  test-6  test-7  test-8  test-9  test-10 \
 	test-11 test-12 test-13 test-14 test-15 test-16 test-17 test-18 test-19 test-20  \
 	test-21 	test-23 test-24 test-25 test-26 test-27 test-28 		 \
-	test-31 test-32 test-33 	test-35 test-37 test-39 test-40 test-42
+	test-31 test-32 test-33 test-34 test-35 test-37 test-39 test-40 test-42 test-43
 
 TEST_NOPASS = \
-	test-22 test-29 test-34
+	test-22 test-29 test-44
 
 test-compiler:
 	-rm *.exe

+ 29 - 4
mcs/tests/test-34.cs

@@ -1,17 +1,33 @@
+//
+// This test tests both how arguments are selected in the presence
+// of ref/out modifiers and the params arguments.
+//
 using System;
 
 public class Blah {
-
+	static int got;
+	
 	public static void Foo (ref int i, ref int j)
 	{
+		got = 1;
 	}
 
-	public static void Bar (int i, params int [] args)
+	public static int Bar (int j, params int [] args)
 	{
+		got = 2;
+		int total = 0;
+		
+		foreach (int i in args){
+			Console.WriteLine ("My argument: " + i);
+			total += i;
+		}
+
+		return total;
 	}
 
 	public static void Foo (int i, int j)
 	{
+		got = 3;
 	}
 
 	public static int Main ()
@@ -20,9 +36,18 @@ public class Blah {
 		int j = 2;
 
 		Foo (i, j);
+		if (got != 3)
+			return 1;
+		
 		Foo (ref i, ref j);
-
-		Bar (i, j, 5, 4, 3, 3, 2);
+		if (got != 1)
+			return 2;
+
+		if (Bar (i, j, 5, 4, 3, 3, 2) != 19)
+			return 4;
+		
+		if (got != 2)
+			return 3;
 
 		return  0;
 	}

+ 34 - 0
mcs/tests/test-44.cs

@@ -0,0 +1,34 @@
+//
+// This test shows that the current way in which we handle blocks
+// and statements is broken.  The b [q,w] code is only executed 10
+// times instead of a 100
+//
+using System;
+
+class X {
+
+	static int dob (int [,]b)
+	{
+		int total = 0;
+		
+		foreach (int i in b)
+			total += i;
+
+		return total;
+	}
+	
+	static void Main ()
+	{
+		int [,] b = new int [10,10];
+
+		for (int q = 0; q < 10; q++)
+			for (int w = 0; w < 10; w++)
+				b [q,w] = q * 10 + w;
+
+		if (dob (b) != 4950)
+			return 1;
+
+		return 0;
+	}
+}
+