return ok;
}
-
- protected void CheckObsolete (Type type)
- {
- ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type);
- if (obsolete_attr == null)
- return;
-
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc);
- }
-
+
/// <summary>
/// Return value indicates whether all code paths emitted return.
/// </summary>
object val = c.GetValue ();
if (val == null)
- val = c;
+ val = SwitchLabel.NullStringCase;
sl = (SwitchLabel) ec.Switch.Elements [val];
if (texpr == null)
return false;
- VariableType = texpr.Type;
+ VariableType = texpr.ResolveType (ec);
}
if (VariableType == TypeManager.void_type) {
if (!unreachable_shown && (RootContext.WarningLevel >= 2)) {
Report.Warning (
- 162, loc, "Unreachable code detected");
+ 162, s.loc, "Unreachable code detected");
unreachable_shown = true;
}
}
Label il_label_code;
bool il_label_code_set;
+ public static readonly object NullStringCase = new object ();
+
//
// if expr == null, then it is the default case.
//
}
if (required_type == TypeManager.string_type && e is NullLiteral) {
- converted = e;
+ converted = NullStringCase;
return true;
}
ig.Emit (OpCodes.Ldloc, val);
- if (Elements.Contains (NullLiteral.Null)){
+ if (Elements.Contains (SwitchLabel.NullStringCase)){
ig.Emit (OpCodes.Brfalse, null_target);
} else
ig.Emit (OpCodes.Brfalse, default_target);
if (sl.Label != null){
object lit = sl.Converted;
- if (lit is NullLiteral){
+ if (lit == SwitchLabel.NullStringCase){
null_found = true;
if (label_count == 1)
ig.Emit (OpCodes.Br, next_test);
public class Lock : ExceptionStatement {
Expression expr;
public Statement Statement;
- LocalBuilder temp;
+ TemporaryVariable temp;
public Lock (Expression expr, Statement stmt, Location l)
{
if (expr.Type.IsValueType){
Report.Error (185, loc,
- "`{0}' is not a reference type as required by the lock statement",
- TypeManager.CSharpName (expr.Type));
+ "`{0}' is not a reference type as required by the lock statement",
+ TypeManager.CSharpName (expr.Type));
return false;
}
ec.NeedReturnLabel ();
}
+ temp = new TemporaryVariable (expr.Type, loc);
+ temp.Resolve (ec);
+
return true;
}
protected override void DoEmit (EmitContext ec)
{
- Type type = expr.Type;
-
ILGenerator ig = ec.ig;
- temp = ig.DeclareLocal (type);
-
- expr.Emit (ec);
- ig.Emit (OpCodes.Dup);
- ig.Emit (OpCodes.Stloc, temp);
+
+ temp.Store (ec, expr);
+ temp.Emit (ec);
ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
// try
public override void EmitFinally (EmitContext ec)
{
- ILGenerator ig = ec.ig;
- ig.Emit (OpCodes.Ldloc, temp);
- ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
+ temp.Emit (ec);
+ ec.ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
}
}
public abstract void EmitExit (ILGenerator ig);
}
- class ExpressionEmitter: Emitter {
+ class ExpressionEmitter : Emitter {
public ExpressionEmitter (Expression converted, LocalInfo li) :
base (converted, li)
{
}
}
- class StringEmitter: Emitter {
+ class StringEmitter : Emitter {
LocalBuilder pinned_string;
Location loc;
if (texpr == null)
return false;
- expr_type = texpr.Type;
-
- CheckObsolete (expr_type);
+ expr_type = texpr.ResolveType (ec);
data = new Emitter [declarators.Count];
if (!TypeManager.VerifyUnManaged (child.Type, loc))
return false;
+ if (!Convert.ImplicitConversionExists (ec, e, expr_type)) {
+ e.Error_ValueCannotBeConverted (e.Location, expr_type, false);
+ return false;
+ }
+
data [i] = new ExpressionEmitter (e, vi);
i++;
}
}
- public class Catch: Statement {
+ public class Catch : Statement {
public readonly string Name;
public readonly Block Block;
type = te.ResolveType (ec);
- CheckObsolete (type);
-
if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){
Error (155, "The type caught or thrown must be derived from System.Exception");
return false;
ArrayList var_list;
Expression expr;
Type expr_type;
- Expression conv;
Expression [] resolved_vars;
Expression [] converted_vars;
ExpressionStatement [] assign;
if (texpr == null)
return false;
- expr_type = texpr.Type;
+ expr_type = texpr.ResolveType (ec);
//
// The type must be an IDisposable or an implicit conversion
continue;
}
- converted_vars [i] = Convert.ImplicitConversionRequired (
+ converted_vars [i] = Convert.ImplicitConversion (
ec, var, TypeManager.idisposable_type, loc);
- if (converted_vars [i] == null)
+ if (converted_vars [i] == null) {
+ Error_IsNotConvertibleToIDisposable ();
return false;
+ }
i++;
}
return true;
}
+ void Error_IsNotConvertibleToIDisposable ()
+ {
+ Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
+ TypeManager.CSharpName (expr_type));
+ }
+
bool ResolveExpression (EmitContext ec)
{
if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
- Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'",
- TypeManager.CSharpName (expr_type));
+ Error_IsNotConvertibleToIDisposable ();
return false;
}
}
//
ILGenerator ig = ec.ig;
local_copy = ig.DeclareLocal (expr_type);
- if (conv != null)
- conv.Emit (ec);
- else
- expr.Emit (ec);
+
+ expr.Emit (ec);
ig.Emit (OpCodes.Stloc, local_copy);
if (emit_finally)
Type var_type = texpr.Type;
+ if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethod) {
+ Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
+ expr.ExprClassName);
+ return false;
+ }
+
//
// We need an instance variable. Not sure this is the best
// way of doing this.
//
if (!(expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.Value ||
expr.eclass == ExprClass.PropertyAccess || expr.eclass == ExprClass.IndexerAccess)){
- collection.error1579 ();
+ collection.Error_Enumerator ();
return false;
}
ec.LoopEnd = old_end;
}
- protected class TemporaryVariable : Expression, IMemoryLocation
- {
- LocalInfo li;
-
- public TemporaryVariable (Type type, Location loc)
- {
- this.type = type;
- this.loc = loc;
- eclass = ExprClass.Value;
- }
-
- public override Expression DoResolve (EmitContext ec)
- {
- if (li != null)
- return this;
-
- TypeExpr te = new TypeExpression (type, loc);
- li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
- if (!li.Resolve (ec))
- return null;
-
- AnonymousContainer am = ec.CurrentAnonymousMethod;
- if ((am != null) && am.IsIterator)
- ec.CaptureVariable (li);
-
- return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- ILGenerator ig = ec.ig;
-
- if (li.FieldBuilder != null) {
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
- } else {
- ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
- }
- }
-
- public void EmitLoadAddress (EmitContext ec)
- {
- ILGenerator ig = ec.ig;
-
- if (li.FieldBuilder != null) {
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
- } else {
- ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
- }
- }
-
- public void Store (EmitContext ec, Expression right_side)
- {
- if (li.FieldBuilder != null)
- ec.ig.Emit (OpCodes.Ldarg_0);
-
- right_side.Emit (ec);
- if (li.FieldBuilder != null) {
- ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
- } else {
- ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
- }
- }
-
- public void EmitThis (EmitContext ec)
- {
- if (li.FieldBuilder != null) {
- ec.ig.Emit (OpCodes.Ldarg_0);
- }
- }
-
- public void EmitStore (ILGenerator ig)
- {
- if (li.FieldBuilder != null)
- ig.Emit (OpCodes.Stfld, li.FieldBuilder);
- else
- ig.Emit (OpCodes.Stloc, li.LocalBuilder);
- }
-
- public void AddressOf (EmitContext ec, AddressOp mode)
- {
- EmitLoadAddress (ec);
- }
- }
-
protected class ArrayCounter : TemporaryVariable
{
public ArrayCounter (Location loc)
MethodInfo move_next;
Type var_type, enumerator_type;
bool is_disposable;
+ bool enumerator_found;
public CollectionForeach (Type var_type, Expression var,
Expression expr, Statement stmt, Location l)
bool GetEnumeratorFilter (EmitContext ec, MethodInfo mi)
{
- Type [] args = TypeManager.GetArgumentTypes (mi);
- if (args != null){
- if (args.Length != 0)
- return false;
- }
-
- if (TypeManager.IsOverride (mi))
- return false;
-
- // Check whether GetEnumerator is public
- if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
- return false;
+ Type return_type = mi.ReturnType;
- if ((mi.ReturnType == TypeManager.ienumerator_type) && (mi.DeclaringType == TypeManager.string_type))
+ if ((return_type == TypeManager.ienumerator_type) && (mi.DeclaringType == TypeManager.string_type))
//
// Apply the same optimization as MS: skip the GetEnumerator
// returning an IEnumerator, and use the one returning a
// with this `GetEnumerator'
//
- Type return_type = mi.ReturnType;
- if (mi.ReturnType == TypeManager.ienumerator_type ||
+ if (return_type == TypeManager.ienumerator_type ||
TypeManager.ienumerator_type.IsAssignableFrom (return_type) ||
(!RootContext.StdLib && TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type))) {
//
// find if they support the GetEnumerator pattern.
//
- if (!FetchMoveNext (ec, return_type))
- return false;
-
- if (!FetchGetCurrent (ec, return_type))
+ if (TypeManager.HasElementType (return_type) || !FetchMoveNext (ec, return_type) || !FetchGetCurrent (ec, return_type)) {
+ Report.Error (202, loc, "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property",
+ TypeManager.CSharpName (return_type), TypeManager.CSharpSignature (mi));
return false;
+ }
}
enumerator_type = return_type;
return null;
}
- public void error1579 ()
+ public void Error_Enumerator ()
{
+ if (enumerator_found) {
+ return;
+ }
+
Report.Error (1579, loc,
- "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `GetEnumerator' or is not accessible",
- TypeManager.CSharpName (expr.Type));
+ "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `GetEnumerator' or is not accessible",
+ TypeManager.CSharpName (expr.Type));
}
bool TryType (EmitContext ec, Type t)
PropertyExpr tmp_get_cur = null;
Type tmp_enumerator_type = enumerator_type;
foreach (MethodInfo mi in mg.Methods) {
+ Type [] args = TypeManager.GetArgumentTypes (mi);
+ if (args != null && args.Length != 0)
+ continue;
+
+ // Check whether GetEnumerator is public
+ if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
+ continue;
+
+ if (TypeManager.IsOverride (mi))
+ continue;
+
+ enumerator_found = true;
+
if (!GetEnumeratorFilter (ec, mi)) {
continue;
}
is_disposable = true;
if (!ProbeCollectionType (ec, expr.Type)) {
- error1579 ();
+ Error_Enumerator ();
return false;
}