2001-12-29 Miguel de Icaza <miguel@ximian.com>
+ * expression.cs (EmitCall): if a method is not virtual, then do
+ not use callvirt on it.
+
+ (ArrayAccess.EmitAssign): storing non-builtin value types (ie,
+ user defined stuff) requires the use of stobj, which takes an
+ address on the stack instead of an array and an index. So emit
+ the Ldelema operation for it.
+
+ (EmitStoreOpcode): Use stobj for valuetypes.
+
+ (UnaryMutator.EmitCode): Use the right 1 value depending on
+ whether we are dealing with int64/uint64, float or doubles.
+
+ * class.cs (TypeContainer.AddConstructor): Fix the logic to define
+ constructors that I implemented last night.
+
+ (Constructor.IsDefault): Fix to work properly for static
+ constructors.
+
+ * cs-parser.jay (CheckDef): report method signature errors.
+ Update error number 103 to be 132.
+
+ * decl.cs: New AdditionResult enumeration value: MethodExists.
+ Although we do this check for methods later on in the semantic
+ analysis, catching repeated default constructors is so easy that
+ we catch these here.
+
* expression.cs (Binary.DoNumericPromotions): Fix the uint64 type
promotions code.
bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
- if (is_static)
+ if (is_static){
have_static_constructor = true;
- else {
+ if (default_static_constructor != null){
+ Console.WriteLine ("I have a static constructor already");
+ Console.WriteLine (" " + default_static_constructor);
+ return AdditionResult.MethodExists;
+ }
+
+ default_static_constructor = c;
+ } else {
+ if (c.IsDefault ()){
+ if (default_constructor != null)
+ return AdditionResult.MethodExists;
+ default_constructor = c;
+ }
+
if (instance_constructors == null)
instance_constructors = new ArrayList ();
instance_constructors.Add (c);
}
- if (c.IsDefault ()) {
- if (is_static)
- default_static_constructor = c;
- else
- default_constructor = c;
- }
-
return AdditionResult.Success;
}
new ConstructorBaseInitializer (null, new Location (-1)),
new Location (-1));
- AddConstructor (c);
-
- c.Block = new Block (null);
-
if (is_static)
mods = Modifiers.STATIC;
c.ModFlags = mods;
+ AddConstructor (c);
+
+ c.Block = new Block (null);
+
}
public void ReportStructInitializedInstanceError ()
//
public bool IsDefault ()
{
- return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
- (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
- (Initializer is ConstructorBaseInitializer) &&
- (Initializer.Arguments == null);
+ if ((ModFlags & Modifiers.STATIC) != 0)
+ return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
+ (Parameters.ArrayParameter == null ? true : Parameters.Empty);
+
+ else
+ return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
+ (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
+ (Initializer is ConstructorBaseInitializer) &&
+ (Initializer.Arguments == null);
}
//
if (!c.Parameters.Empty){
Location l = lexer.Location;
- Report.Error (103, l, "Static constructors should not have parameters");
+ Report.Error (132, l, "Static constructors should not have parameters");
}
}
break;
-// NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
-//
-// case AdditionResult.MethodDuplicated:
-// error (111, "Class `"+current_container.Name+
-// "' already defines a member called '" +
-// name + "' with the same parameter types");
-// break;
+ //
+ // This is handled only for static Constructors, because
+ // in reality we handle these by the semantic analysis later
+ //
+ case AdditionResult.MethodExists:
+ Report.Error (
+ 111, l, "Class `"+current_container.Name+
+ "' already defines a member called '" +
+ name + "' with the same parameter types (more than one default constructor)");
+ break;
case AdditionResult.EnclosingClash:
Report.Error (542, l, "Member names cannot be the same as their enclosing type");
/// it looked like a constructor) but was not (because the name
/// of the method is not the same as the container class
/// </summary>
- NotAConstructor
+ NotAConstructor,
+
+ /// <summary>
+ /// This is only used by static constructors to emit the
+ /// error 111, but this error for other things really
+ /// happens at another level for other functions.
+ /// </summary>
+ MethodExists
}
/// <summary>
{
ILGenerator ig = ec.ig;
IAssignMethod ia = (IAssignMethod) expr;
-
- if (temp_storage == null)
- temp_storage = new LocalTemporary (ec, expr.Type);
+ Type expr_type = expr.Type;
+ if (temp_storage == null)
+ temp_storage = new LocalTemporary (ec, expr_type);
+
switch (mode){
case Mode.PreIncrement:
case Mode.PreDecrement:
if (method == null){
expr.Emit (ec);
- ig.Emit (OpCodes.Ldc_I4_1);
+ if (expr_type == TypeManager.uint64_type ||
+ expr_type == TypeManager.int64_type)
+ ig.Emit (OpCodes.Ldc_I8, 1L);
+ else if (expr_type == TypeManager.double_type)
+ ig.Emit (OpCodes.Ldc_R8, 1.0);
+ else if (expr_type == TypeManager.float_type)
+ ig.Emit (OpCodes.Ldc_R4, 1.0F);
+ else
+ ig.Emit (OpCodes.Ldc_I4_1);
if (mode == Mode.PreDecrement)
ig.Emit (OpCodes.Sub);
else
ig.Emit (OpCodes.Dup);
- ig.Emit (OpCodes.Ldc_I4_1);
+ if (expr_type == TypeManager.uint64_type ||
+ expr_type == TypeManager.int64_type)
+ ig.Emit (OpCodes.Ldc_I8, 1L);
+ else if (expr_type == TypeManager.double_type)
+ ig.Emit (OpCodes.Ldc_R8, 1.0);
+ else if (expr_type == TypeManager.float_type)
+ ig.Emit (OpCodes.Ldc_R4, 1.0F);
+ else
+ ig.Emit (OpCodes.Ldc_I4_1);
if (mode == Mode.PostDecrement)
ig.Emit (OpCodes.Sub);
// reference-type with a value-type argument need
// to have their value boxed.
+ struct_call = true;
if (method.DeclaringType.IsValueType){
- struct_call = true;
-
//
// If the expression implements IMemoryLocation, then
// we can optimize and use AddressOf on the
if (Arguments != null)
EmitArguments (ec, method, Arguments);
+ if (method is MethodInfo){
+ MethodInfo mi = (MethodInfo) method;
+
+ if (!mi.IsVirtual)
+ is_static = true;
+ }
+
if (is_static || struct_call){
if (method is MethodInfo)
ig.Emit (OpCodes.Call, (MethodInfo) method);
return null;
}
}
-
+
method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
Arguments, loc);
+
}
if (method == null && !is_struct) {
ig.Emit (OpCodes.Ldelem_R8);
else if (type == TypeManager.intptr_type)
ig.Emit (OpCodes.Ldelem_I);
- else if (type.IsValueType)
+ else if (type.IsValueType){
ig.Emit (OpCodes.Ldelema, type);
- else
+ ig.Emit (OpCodes.Ldobj, type);
+ } else
ig.Emit (OpCodes.Ldelem_Ref);
}
ig.Emit (OpCodes.Stelem_R8);
else if (t == TypeManager.intptr_type)
ig.Emit (OpCodes.Stelem_I);
+ else if (t.IsValueType)
+ ig.Emit (OpCodes.Stobj, t);
else
ig.Emit (OpCodes.Stelem_Ref);
}
foreach (Argument a in ea.Arguments)
a.Expr.Emit (ec);
- source.Emit (ec);
-
Type t = source.Type;
+ //
+ // The stobj opcode used by value types will need
+ // an address on the stack, not really an array/array
+ // pair
+ //
+ if (rank == 1){
+ if (t.IsValueType && !TypeManager.IsBuiltinType (t))
+ ig.Emit (OpCodes.Ldelema, t);
+ }
+
+ source.Emit (ec);
+
if (rank == 1)
EmitStoreOpcode (ig, t);
else {
return false;
}
+ //
+ // UGH: Non trivial. This Br might cross a try/catch boundary
+ // How can we tell?
+ //
+ // while () {
+ // try { ... } catch { continue; }
+ // }
+ //
+ // From:
+ // try {} catch { while () { continue; }}
+ //
ec.ig.Emit (OpCodes.Br, begin);
return false;
}