return false;
}
+ Assign ass = expr as Assign;
+ if (ass != null && ass.Source is Constant) {
+ Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
+ }
+
//
// Dead code elimination
//
public override bool Resolve (EmitContext ec)
{
- expr = expr.ResolveStatement (ec);
+ if (expr != null)
+ expr = expr.ResolveStatement (ec);
return expr != null;
}
return false;
}
+ if (ec.InIterator) {
+ Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
+ "statement to return a value, or yield break to end the iteration");
+ return false;
+ }
+
Expr = Expr.Resolve (ec);
if (Expr == null)
return false;
label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
ec.CurrentBranching.CurrentUsageVector.Goto ();
+ label.AddReference ();
return true;
}
bool defined;
bool referenced;
Label label;
+ ILGenerator ig;
FlowBranching.UsageVector vectors;
{
if (defined)
return label;
+ ig = ec.ig;
label = ec.ig.DefineLabel ();
defined = true;
{
ec.CurrentBranching.Label (vectors);
- referenced = true;
-
return true;
}
protected override void DoEmit (EmitContext ec)
{
+ if (ig != null && ig != ec.ig) {
+ Report.Error (1632, "Control cannot leave body of anonymous method");
+ return;
+ }
LabelTarget (ec);
ec.ig.MarkLabel (label);
}
+
+ public void AddReference ()
+ {
+ referenced = true;
+ }
}
// </summary>
public LocalInfo ThisVariable {
get {
- if (this_variable != null)
- return this_variable;
- else if (Parent != null)
- return Parent.ThisVariable;
- else
- return null;
+ for (Block b = this; b != null; b = b.Parent) {
+ if (b.this_variable != null)
+ return b.this_variable;
+ }
+
+ return null;
}
}
if (variables == null)
variables = new Hashtable ();
+ Block cur = this;
+ while (cur != null && cur.Implicit)
+ cur = cur.Parent;
+
LocalInfo vi = GetLocalInfo (name);
if (vi != null) {
- if (vi.Block != this)
+ Block var = vi.Block;
+ while (var != null && var.Implicit)
+ var = var.Parent;
+ if (var != cur)
Report.Error (136, l, "A local variable named `" + name + "' " +
"cannot be declared in this scope since it would " +
"give a different meaning to `" + name + "', which " +
variables.Add (name, vi);
// Mark 'name' as "used by a child block" in every surrounding block
- Block cur = this;
- while (cur != null && cur.Implicit)
- cur = cur.Parent;
if (cur != null)
for (Block par = cur.Parent; par != null; par = par.Parent)
par.AddChildVariableName (name);
par = pars.GetParameterByName (name, out idx);
if (par != null){
- ParameterReference pr;
-
- pr = new ParameterReference (pars, this, idx, name, loc);
- return pr;
+ return new ParameterReference (pars, this, idx, name, loc);
}
}
b = b.Parent;
Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
- bool unreachable = false;
+ bool unreachable = unreachable_shown;
int statement_count = statements.Count;
for (int ix = 0; ix < statement_count; ix++){
else
s.loc = Location.Null;
- statements [ix] = EmptyStatement.Value;
- continue;
+ if (ok && !(s is Block)) {
+ statements [ix] = EmptyStatement.Value;
+ continue;
+ }
}
if (s.Resolve (ec) == false) {
public override bool ResolveUnreachable (EmitContext ec, bool warn)
{
unreachable_shown = true;
- return base.ResolveUnreachable (ec, warn);
+
+ if (warn && (RootContext.WarningLevel >= 2))
+ Report.Warning (162, loc, "Unreachable code detected");
+
+ if (Implicit)
+ return Resolve (ec);
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
+ bool ok = Resolve (ec);
+ ec.KillFlowBranching ();
+
+ return ok;
}
protected override void DoEmit (EmitContext ec)
// Check whether we are the last statement in a
// top-level block.
- if ((Parent == null) && (ix+1 == num_statements))
+ if (((Parent == null) || Implicit) && (ix+1 == num_statements) && !(s is Block))
ec.IsLastStatement = true;
else
ec.IsLastStatement = false;
if (emit_debug_info) {
if (is_lexical_block)
- ec.ig.BeginScope ();
+ ec.BeginScope ();
if (variables != null) {
foreach (DictionaryEntry de in variables) {
ec.Mark (EndLocation, true);
if (emit_debug_info && is_lexical_block)
- ec.ig.EndScope ();
+ ec.EndScope ();
ec.CurrentBlock = prev_block;
}
ArrayList declarators;
Statement statement;
Type expr_type;
- FixedData[] data;
+ Emitter[] data;
bool has_ret;
- struct FixedData {
- public bool is_object;
- public LocalInfo vi;
- public Expression expr;
- public Expression converted;
- }
+ abstract class Emitter
+ {
+ protected LocalInfo vi;
+ protected Expression converted;
+
+ protected Emitter (Expression expr, LocalInfo li)
+ {
+ converted = expr;
+ vi = li;
+ }
+
+ public abstract void Emit (EmitContext ec);
+ public abstract void EmitExit (ILGenerator ig);
+ }
+
+ class ExpressionEmitter: Emitter {
+ public ExpressionEmitter (Expression converted, LocalInfo li) :
+ base (converted, li)
+ {
+ }
+
+ public override void Emit (EmitContext ec) {
+ //
+ // Store pointer in pinned location
+ //
+ converted.Emit (ec);
+ ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+
+ public override void EmitExit (ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Conv_U);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+ }
+
+ class StringEmitter: Emitter {
+ LocalBuilder pinned_string;
+ Location loc;
+
+ public StringEmitter (Expression expr, LocalInfo li, Location loc):
+ base (expr, li)
+ {
+ this.loc = loc;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
+
+ converted.Emit (ec);
+ ig.Emit (OpCodes.Stloc, pinned_string);
+
+ Expression sptr = new StringPtr (pinned_string, loc);
+ converted = Convert.ImplicitConversionRequired (
+ ec, sptr, vi.VariableType, loc);
+
+ if (converted == null)
+ return;
+
+ converted.Emit (ec);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
+
+ public override void EmitExit(ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldnull);
+ ig.Emit (OpCodes.Stloc, pinned_string);
+ }
+ }
public Fixed (Expression type, ArrayList decls, Statement stmt, Location l)
{
return false;
}
- data = new FixedData [declarators.Count];
+ data = new Emitter [declarators.Count];
if (!expr_type.IsPointer){
Report.Error (209, loc, "Variables in a fixed statement must be pointers");
if (!TypeManager.VerifyUnManaged (child.Type, loc))
return false;
- data [i].is_object = true;
- data [i].expr = e;
- data [i].converted = null;
- data [i].vi = vi;
+ data [i] = new ExpressionEmitter (e, vi);
i++;
continue;
// and T* is implicitly convertible to the
// pointer type given in the fixed statement.
//
- ArrayPtr array_ptr = new ArrayPtr (e, loc);
+ ArrayPtr array_ptr = new ArrayPtr (e, array_type, loc);
Expression converted = Convert.ImplicitConversionRequired (
ec, array_ptr, vi.VariableType, loc);
if (converted == null)
return false;
- data [i].is_object = false;
- data [i].expr = e;
- data [i].converted = converted;
- data [i].vi = vi;
+ data [i] = new ExpressionEmitter (converted, vi);
i++;
continue;
// Case 3: string
//
if (e.Type == TypeManager.string_type){
- data [i].is_object = false;
- data [i].expr = e;
- data [i].converted = null;
- data [i].vi = vi;
+ data [i] = new StringEmitter (e, vi, loc);
i++;
continue;
}
+ // Case 4: fixed buffer
+ FieldExpr fe = e as FieldExpr;
+ if (fe != null) {
+ IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
+ if (ff != null) {
+ Expression fixed_buffer_ptr = new FixedBufferPtr (fe, ff.ElementType, loc);
+
+ Expression converted = Convert.ImplicitConversionRequired (
+ ec, fixed_buffer_ptr, vi.VariableType, loc);
+ if (converted == null)
+ return false;
+
+ data [i] = new ExpressionEmitter (converted, vi);
+ i++;
+
+ continue;
+ }
+ }
+
//
// For other cases, flag a `this is already fixed expression'
//
protected override void DoEmit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
- LocalBuilder [] clear_list = new LocalBuilder [data.Length];
-
for (int i = 0; i < data.Length; i++) {
- LocalInfo vi = data [i].vi;
-
- //
- // Case 1: & object.
- //
- if (data [i].is_object) {
- //
- // Store pointer in pinned location
- //
- data [i].expr.Emit (ec);
- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
- clear_list [i] = vi.LocalBuilder;
- continue;
- }
-
- //
- // Case 2: Array
- //
- if (data [i].expr.Type.IsArray){
- //
- // Store pointer in pinned location
- //
- data [i].converted.Emit (ec);
-
- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
- clear_list [i] = vi.LocalBuilder;
- continue;
- }
-
- //
- // Case 3: string
- //
- if (data [i].expr.Type == TypeManager.string_type){
- LocalBuilder pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
- clear_list [i] = pinned_string;
-
- data [i].expr.Emit (ec);
- ig.Emit (OpCodes.Stloc, pinned_string);
-
- Expression sptr = new StringPtr (pinned_string, loc);
- Expression converted = Convert.ImplicitConversionRequired (
- ec, sptr, vi.VariableType, loc);
-
- if (converted == null)
- continue;
-
- converted.Emit (ec);
- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
- }
+ data [i].Emit (ec);
}
statement.Emit (ec);
if (has_ret)
return;
+ ILGenerator ig = ec.ig;
+
//
// Clear the pinned variable
//
for (int i = 0; i < data.Length; i++) {
- if (data [i].is_object || data [i].expr.Type.IsArray) {
- ig.Emit (OpCodes.Ldc_I4_0);
- ig.Emit (OpCodes.Conv_U);
- ig.Emit (OpCodes.Stloc, clear_list [i]);
- } else if (data [i].expr.Type == TypeManager.string_type){
- ig.Emit (OpCodes.Ldnull);
- ig.Emit (OpCodes.Stloc, clear_list [i]);
- }
+ data [i].EmitExit (ig);
}
}
}
if (expr == null)
return false;
+ if (expr is NullLiteral) {
+ Report.Error (186, expr.Location, "Use of null is not valid in this context");
+ return false;
+ }
+
TypeExpr texpr = type.ResolveAsTypeTerminal (ec, false);
if (texpr == null)
return false;
ig.Emit (OpCodes.Brfalse, end_try);
if (ec.InIterator)
- enumerator.EmitThis (ig);
+ ig.Emit (OpCodes.Ldarg_0);
+
enumerator.EmitCall (ig, hm.get_current);
if (ec.InIterator){
ig.MarkLabel (loop);
if (ec.InIterator)
- ec.EmitThis ();
+ ig.Emit (OpCodes.Ldarg_0);
copy.EmitThis (ig);
copy.EmitLoad (ig);
}
if (ec.InIterator)
- ec.EmitThis ();
+ ig.Emit (OpCodes.Ldarg_0);
+
copy.EmitThis (ig);
copy.EmitLoad (ig);
for (dim = 0; dim < rank; dim++){