Author: raja
Date: 2006-07-22 09:37:53 -0400 (Sat, 22 Jul 2006)
New Revision: 62896
Modified:
trunk/mcs/gmcs/ChangeLog
trunk/mcs/gmcs/codegen.cs
trunk/mcs/gmcs/statement.cs
trunk/mcs/mcs/ChangeLog
trunk/mcs/mcs/codegen.cs
trunk/mcs/mcs/statement.cs
Log:
* codegen.cs (EmitContext.Flags): New enum. Used to represent the
multiple boolean fields. Convert InUnsafe, constant_check_state,
check_state to flags.
(CheckState, ConstantCheckState): Update.
(InUnsafe): New read-only property.
(FlagsHandle): Rename from CheckStateHandle and convert to handle
arbitrary flags.
(WithUnsafe): New helper similar to WithCheckState.
* statement.cs (Block.ResolveMeta): Use WithUnsafe.
(Unsafe.Resolve, Unsafe.DoEmit): Likewise.
Modified: trunk/mcs/gmcs/ChangeLog
===================================================================
--- trunk/mcs/gmcs/ChangeLog 2006-07-22 11:13:31 UTC (rev 62895)
+++ trunk/mcs/gmcs/ChangeLog 2006-07-22 13:37:53 UTC (rev 62896)
@@ -1,3 +1,16 @@
+2006-07-22 Raja R Harinath <[EMAIL PROTECTED]>
+
+ * codegen.cs (EmitContext.Flags): New enum. Used to represent the
+ multiple boolean fields. Convert InUnsafe, constant_check_state,
+ check_state to flags.
+ (CheckState, ConstantCheckState): Update.
+ (InUnsafe): New read-only property.
+ (FlagsHandle): Rename from CheckStateHandle and convert to handle
+ arbitrary flags.
+ (WithUnsafe): New helper similar to WithCheckState.
+ * statement.cs (Block.ResolveMeta): Use WithUnsafe.
+ (Unsafe.Resolve, Unsafe.DoEmit): Likewise.
+
2006-07-21 Raja R Harinath <[EMAIL PROTECTED]>
Make comparisons use the same IL irrespective of whether they're
Modified: trunk/mcs/gmcs/codegen.cs
===================================================================
--- trunk/mcs/gmcs/codegen.cs 2006-07-22 11:13:31 UTC (rev 62895)
+++ trunk/mcs/gmcs/codegen.cs 2006-07-22 13:37:53 UTC (rev 62896)
@@ -209,25 +209,35 @@
public DeclSpace TypeContainer;
public ILGenerator ig;
- /// <summary>
- /// This variable tracks the `checked' state of the
compilation,
- /// it controls whether we should generate code that does
overflow
- /// checking, or if we generate code that ignores overflows.
- ///
- /// The default setting comes from the command line option to
generate
- /// checked or unchecked code plus any source code changes
using the
- /// checked/unchecked statements or expressions. Contrast
this with
- /// the constant_check_state flag.
- /// </summary>
- bool check_state;
+ [Flags]
+ internal enum Flags : byte {
+ /// <summary>
+ /// This flag tracks the `checked' state of the
compilation,
+ /// it controls whether we should generate code that
does overflow
+ /// checking, or if we generate code that ignores
overflows.
+ ///
+ /// The default setting comes from the command line
option to generate
+ /// checked or unchecked code plus any source code
changes using the
+ /// checked/unchecked statements or expressions.
Contrast this with
+ /// the ConstantCheckState flag.
+ /// </summary>
+ CheckState = 1 << 0,
- /// <summary>
- /// The constant check state is always set to `true' and cant
be changed
- /// from the command line. The source code can change this
setting with
- /// the `checked' and `unchecked' statements and expressions.
- /// </summary>
- bool constant_check_state;
+ /// <summary>
+ /// The constant check state is always set to `true'
and cant be changed
+ /// from the command line. The source code can
change this setting with
+ /// the `checked' and `unchecked' statements and
expressions.
+ /// </summary>
+ ConstantCheckState = 1 << 1,
+ /// <summary>
+ /// Whether we are inside an unsafe block
+ /// </summary>
+ InUnsafe = 1 << 2
+ }
+
+ Flags flags;
+
/// <summary>
/// Whether we are emitting code inside a static or instance
method
/// </summary>
@@ -310,11 +320,6 @@
public bool IsLastStatement;
/// <summary>
- /// Whether we are inside an unsafe block
- /// </summary>
- public bool InUnsafe;
-
- /// <summary>
/// Whether we are in a `fixed' initialization
/// </summary>
public bool InFixedInitializer;
@@ -394,8 +399,9 @@
TypeContainer = parent;
this.declSpace = ds;
- check_state = RootContext.Checked;
- constant_check_state = true;
+ if (RootContext.Checked)
+ flags |= Flags.CheckState;
+ flags |= Flags.ConstantCheckState;
if ((return_type is TypeBuilder) &&
return_type.IsGenericTypeDefinition)
throw new InternalErrorException ();
@@ -408,11 +414,12 @@
CurrentBlock = null;
CurrentFile = 0;
current_phase = Phase.Created;
-
+
if (parent != null){
// Can only be null for the ResolveType
contexts.
ContainerType = parent.TypeBuilder;
- InUnsafe = rc.IsInUnsafeScope;
+ if (rc.IsInUnsafeScope)
+ flags |= Flags.InUnsafe;
}
loc = l;
@@ -438,40 +445,50 @@
}
public bool CheckState {
- get { return check_state; }
+ get { return (flags & Flags.CheckState) != 0; }
}
public bool ConstantCheckState {
- get { return constant_check_state; }
+ get { return (flags & Flags.ConstantCheckState) != 0; }
}
+ public bool InUnsafe {
+ get { return (flags & Flags.InUnsafe) != 0; }
+ }
+
// utility helper for CheckExpr, UnCheckExpr, Checked and
Unchecked statements
// it's public so that we can use a struct at the callsite
- public struct CheckStateHandle : IDisposable
+ public struct FlagsHandle : IDisposable
{
EmitContext ec;
- bool check, const_check;
- public CheckStateHandle (EmitContext ec, bool
new_check_state, bool new_constant_check_state)
+ Flags invmask, oldval;
+ internal FlagsHandle (EmitContext ec, Flags mask, Flags
val)
{
this.ec = ec;
- check = ec.check_state;
- const_check = ec.constant_check_state;
- ec.check_state = new_check_state;
- ec.constant_check_state =
new_constant_check_state;
+ invmask = ~mask;
+ oldval = ec.flags & mask;
+ ec.flags = (ec.flags & invmask) | (val & mask);
}
void IDisposable.Dispose ()
{
- ec.check_state = check;
- ec.constant_check_state = const_check;
+ ec.flags = (ec.flags & invmask) | oldval;
}
}
// Temporarily set 'CheckState' and 'ConstantCheckState' to the
given values.
// Should be used in an 'using' statement
- public CheckStateHandle WithCheckState (bool check_state, bool
constant_check_state)
+ public FlagsHandle WithCheckState (bool check_state, bool
constant_check_state)
{
- return new CheckStateHandle (this, check_state,
constant_check_state);
+ Flags newflags = 0;
+ newflags |= check_state ? Flags.CheckState
: 0;
+ newflags |= constant_check_state ?
Flags.ConstantCheckState : 0;
+ return new FlagsHandle (this, Flags.CheckState |
Flags.ConstantCheckState, newflags);
}
+
+ public FlagsHandle WithUnsafe (bool in_unsafe)
+ {
+ return new FlagsHandle (this, Flags.InUnsafe, in_unsafe
? Flags.InUnsafe : 0);
+ }
public bool IsInObsoleteScope {
get { return ResolveContext.IsInObsoleteScope; }
Modified: trunk/mcs/gmcs/statement.cs
===================================================================
--- trunk/mcs/gmcs/statement.cs 2006-07-22 11:13:31 UTC (rev 62895)
+++ trunk/mcs/gmcs/statement.cs 2006-07-22 13:37:53 UTC (rev 62896)
@@ -1688,108 +1688,105 @@
/// </remarks>
public void ResolveMeta (ToplevelBlock toplevel, EmitContext
ec, Parameters ip)
{
- bool old_unsafe = ec.InUnsafe;
-
// If some parent block was unsafe, we remain unsafe
even if this block
// isn't explicitly marked as such.
- ec.InUnsafe |= Unsafe;
+ using (ec.WithUnsafe (ec.InUnsafe | Unsafe)) {
+ //
+ // Compute the VariableMap's.
+ //
+ // Unfortunately, we don't know the type when
adding variables with
+ // AddVariable(), so we need to compute this
info here.
+ //
- //
- // Compute the VariableMap's.
- //
- // Unfortunately, we don't know the type when adding
variables with
- // AddVariable(), so we need to compute this info here.
- //
+ LocalInfo[] locals;
+ if (variables != null) {
+ foreach (LocalInfo li in
variables.Values)
+ li.Resolve (ec);
- LocalInfo[] locals;
- if (variables != null) {
- foreach (LocalInfo li in variables.Values)
- li.Resolve (ec);
+ locals = new LocalInfo
[variables.Count];
+ variables.Values.CopyTo (locals, 0);
+ } else
+ locals = new LocalInfo [0];
- locals = new LocalInfo [variables.Count];
- variables.Values.CopyTo (locals, 0);
- } else
- locals = new LocalInfo [0];
+ if (Parent != null)
+ local_map = new VariableMap
(Parent.LocalMap, locals);
+ else
+ local_map = new VariableMap (locals);
- if (Parent != null)
- local_map = new VariableMap (Parent.LocalMap,
locals);
- else
- local_map = new VariableMap (locals);
+ param_map = new VariableMap (ip);
+ flags |= Flags.VariablesInitialized;
- param_map = new VariableMap (ip);
- flags |= Flags.VariablesInitialized;
+ //
+ // Process this block variables
+ //
+ if (variables != null){
+ using (ec.WithCheckState
(ec.CheckState, (flags & Flags.Unchecked) == 0)) {
+ foreach (DictionaryEntry de in
variables) {
+ string name = (string)
de.Key;
+ LocalInfo vi =
(LocalInfo) de.Value;
- //
- // Process this block variables
- //
- if (variables != null){
- using (ec.WithCheckState (ec.CheckState, (flags
& Flags.Unchecked) == 0)) {
- foreach (DictionaryEntry de in
variables) {
- string name = (string) de.Key;
- LocalInfo vi = (LocalInfo)
de.Value;
+ if (vi.VariableType ==
null)
+ continue;
- if (vi.VariableType == null)
- continue;
+ Type variable_type =
vi.VariableType;
- Type variable_type =
vi.VariableType;
+ if
(variable_type.IsPointer) {
+ //
+ // Am not
really convinced that this test is required (Microsoft does it)
+ // but the fact
is that you would not be able to use the pointer variable
+ // *anyways*
+ //
+ if
(!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),
+
vi.Location))
+
continue;
+ }
- if (variable_type.IsPointer) {
- //
- // Am not really
convinced that this test is required (Microsoft does it)
- // but the fact is that
you would not be able to use the pointer variable
- // *anyways*
- //
- if
(!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),
-
vi.Location))
+ if (constants == null)
continue;
- }
- if (constants == null)
- continue;
+ Expression cv =
(Expression) constants [name];
+ if (cv == null)
+ continue;
- Expression cv = (Expression)
constants [name];
- if (cv == null)
- continue;
+ // Don't let 'const int
Foo = Foo;' succeed.
+ // Removing the name
from 'constants' ensures that we get a LocalVariableReference below,
+ // which in turn causes
the 'must be constant' error to be triggered.
+ constants.Remove (name);
- // Don't let 'const int Foo =
Foo;' succeed.
- // Removing the name from
'constants' ensures that we get a LocalVariableReference below,
- // which in turn causes the
'must be constant' error to be triggered.
- constants.Remove (name);
+ ec.CurrentBlock = this;
+ Expression e =
cv.Resolve (ec);
+ if (e == null)
+ continue;
- ec.CurrentBlock = this;
- Expression e = cv.Resolve (ec);
- if (e == null)
- continue;
+ Constant ce = e as
Constant;
+ if (ce == null) {
+
Const.Error_ExpressionMustBeConstant (variable_type, vi.Location, name);
+ continue;
+ }
- Constant ce = e as Constant;
- if (ce == null) {
-
Const.Error_ExpressionMustBeConstant (variable_type, vi.Location, name);
- continue;
- }
+ e = ce.ToType
(variable_type, vi.Location);
+ if (e == null)
+ continue;
- e = ce.ToType (variable_type,
vi.Location);
- if (e == null)
- continue;
+ if
(!variable_type.IsValueType && variable_type != TypeManager.string_type &&
!ce.IsDefaultValue) {
+
Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
+ continue;
+ }
- if (!variable_type.IsValueType
&& variable_type != TypeManager.string_type && !ce.IsDefaultValue) {
-
Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
- continue;
+ constants.Add (name, e);
+ vi.IsConstant = true;
}
-
- constants.Add (name, e);
- vi.IsConstant = true;
}
}
- }
- //
- // Now, handle the children
- //
- if (children != null){
- foreach (Block b in children)
- b.ResolveMeta (toplevel, ec, ip);
+ //
+ // Now, handle the children
+ //
+ if (children != null) {
+ foreach (Block b in children)
+ b.ResolveMeta (toplevel, ec,
ip);
+ }
}
- ec.InUnsafe = old_unsafe;
}
//
@@ -3269,23 +3266,14 @@
public override bool Resolve (EmitContext ec)
{
- bool previous_state = ec.InUnsafe;
- bool val;
-
- ec.InUnsafe = true;
- val = Block.Resolve (ec);
- ec.InUnsafe = previous_state;
-
- return val;
+ using (ec.WithUnsafe (true))
+ return Block.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
{
- bool previous_state = ec.InUnsafe;
-
- ec.InUnsafe = true;
- Block.Emit (ec);
- ec.InUnsafe = previous_state;
+ using (ec.WithUnsafe (true))
+ Block.Emit (ec);
}
}
Modified: trunk/mcs/mcs/ChangeLog
===================================================================
--- trunk/mcs/mcs/ChangeLog 2006-07-22 11:13:31 UTC (rev 62895)
+++ trunk/mcs/mcs/ChangeLog 2006-07-22 13:37:53 UTC (rev 62896)
@@ -1,3 +1,16 @@
+2006-07-22 Raja R Harinath <[EMAIL PROTECTED]>
+
+ * codegen.cs (EmitContext.Flags): New enum. Used to represent the
+ multiple boolean fields. Convert InUnsafe, constant_check_state,
+ check_state to flags.
+ (CheckState, ConstantCheckState): Update.
+ (InUnsafe): New read-only property.
+ (FlagsHandle): Rename from CheckStateHandle and convert to handle
+ arbitrary flags.
+ (WithUnsafe): New helper similar to WithCheckState.
+ * statement.cs (Block.ResolveMeta): Use WithUnsafe.
+ (Unsafe.Resolve, Unsafe.DoEmit): Likewise.
+
2006-07-21 Raja R Harinath <[EMAIL PROTECTED]>
Make comparisons use the same IL irrespective of whether they're
Modified: trunk/mcs/mcs/codegen.cs
===================================================================
--- trunk/mcs/mcs/codegen.cs 2006-07-22 11:13:31 UTC (rev 62895)
+++ trunk/mcs/mcs/codegen.cs 2006-07-22 13:37:53 UTC (rev 62896)
@@ -205,25 +205,35 @@
public DeclSpace TypeContainer;
public ILGenerator ig;
- /// <summary>
- /// This variable tracks the `checked' state of the
compilation,
- /// it controls whether we should generate code that does
overflow
- /// checking, or if we generate code that ignores overflows.
- ///
- /// The default setting comes from the command line option to
generate
- /// checked or unchecked code plus any source code changes
using the
- /// checked/unchecked statements or expressions. Contrast
this with
- /// the constant_check_state flag.
- /// </summary>
- bool check_state;
+ [Flags]
+ internal enum Flags : byte {
+ /// <summary>
+ /// This flag tracks the `checked' state of the
compilation,
+ /// it controls whether we should generate code that
does overflow
+ /// checking, or if we generate code that ignores
overflows.
+ ///
+ /// The default setting comes from the command line
option to generate
+ /// checked or unchecked code plus any source code
changes using the
+ /// checked/unchecked statements or expressions.
Contrast this with
+ /// the ConstantCheckState flag.
+ /// </summary>
+ CheckState = 1 << 0,
- /// <summary>
- /// The constant check state is always set to `true' and cant
be changed
- /// from the command line. The source code can change this
setting with
- /// the `checked' and `unchecked' statements and expressions.
- /// </summary>
- bool constant_check_state;
+ /// <summary>
+ /// The constant check state is always set to `true'
and cant be changed
+ /// from the command line. The source code can
change this setting with
+ /// the `checked' and `unchecked' statements and
expressions.
+ /// </summary>
+ ConstantCheckState = 1 << 1,
+ /// <summary>
+ /// Whether we are inside an unsafe block
+ /// </summary>
+ InUnsafe = 1 << 2
+ }
+
+ Flags flags;
+
/// <summary>
/// Whether we are emitting code inside a static or instance
method
/// </summary>
@@ -306,11 +316,6 @@
public bool IsLastStatement;
/// <summary>
- /// Whether we are inside an unsafe block
- /// </summary>
- public bool InUnsafe;
-
- /// <summary>
/// Whether we are in a `fixed' initialization
/// </summary>
public bool InFixedInitializer;
@@ -383,8 +388,9 @@
TypeContainer = parent;
this.declSpace = ds;
- check_state = RootContext.Checked;
- constant_check_state = true;
+ if (RootContext.Checked)
+ flags |= Flags.CheckState;
+ flags |= Flags.ConstantCheckState;
IsStatic = (code_flags & Modifiers.STATIC) != 0;
MethodIsStatic = IsStatic;
@@ -394,11 +400,12 @@
CurrentBlock = null;
CurrentFile = 0;
current_phase = Phase.Created;
-
+
if (parent != null){
// Can only be null for the ResolveType
contexts.
ContainerType = parent.TypeBuilder;
- InUnsafe = rc.IsInUnsafeScope;
+ if (rc.IsInUnsafeScope)
+ flags |= Flags.InUnsafe;
}
loc = l;
@@ -424,40 +431,50 @@
}
public bool CheckState {
- get { return check_state; }
+ get { return (flags & Flags.CheckState) != 0; }
}
public bool ConstantCheckState {
- get { return constant_check_state; }
+ get { return (flags & Flags.ConstantCheckState) != 0; }
}
+ public bool InUnsafe {
+ get { return (flags & Flags.InUnsafe) != 0; }
+ }
+
// utility helper for CheckExpr, UnCheckExpr, Checked and
Unchecked statements
// it's public so that we can use a struct at the callsite
- public struct CheckStateHandle : IDisposable
+ public struct FlagsHandle : IDisposable
{
EmitContext ec;
- bool check, const_check;
- public CheckStateHandle (EmitContext ec, bool
new_check_state, bool new_constant_check_state)
+ Flags invmask, oldval;
+ internal FlagsHandle (EmitContext ec, Flags mask, Flags
val)
{
this.ec = ec;
- check = ec.check_state;
- const_check = ec.constant_check_state;
- ec.check_state = new_check_state;
- ec.constant_check_state =
new_constant_check_state;
+ invmask = ~mask;
+ oldval = ec.flags & mask;
+ ec.flags = (ec.flags & invmask) | (val & mask);
}
void IDisposable.Dispose ()
{
- ec.check_state = check;
- ec.constant_check_state = const_check;
+ ec.flags = (ec.flags & invmask) | oldval;
}
}
// Temporarily set 'CheckState' and 'ConstantCheckState' to the
given values.
// Should be used in an 'using' statement
- public CheckStateHandle WithCheckState (bool check_state, bool
constant_check_state)
+ public FlagsHandle WithCheckState (bool check_state, bool
constant_check_state)
{
- return new CheckStateHandle (this, check_state,
constant_check_state);
+ Flags newflags = 0;
+ newflags |= check_state ? Flags.CheckState
: 0;
+ newflags |= constant_check_state ?
Flags.ConstantCheckState : 0;
+ return new FlagsHandle (this, Flags.CheckState |
Flags.ConstantCheckState, newflags);
}
+
+ public FlagsHandle WithUnsafe (bool in_unsafe)
+ {
+ return new FlagsHandle (this, Flags.InUnsafe, in_unsafe
? Flags.InUnsafe : 0);
+ }
public bool IsInObsoleteScope {
get { return ResolveContext.IsInObsoleteScope; }
Modified: trunk/mcs/mcs/statement.cs
===================================================================
--- trunk/mcs/mcs/statement.cs 2006-07-22 11:13:31 UTC (rev 62895)
+++ trunk/mcs/mcs/statement.cs 2006-07-22 13:37:53 UTC (rev 62896)
@@ -1688,108 +1688,105 @@
/// </remarks>
public void ResolveMeta (ToplevelBlock toplevel, EmitContext
ec, Parameters ip)
{
- bool old_unsafe = ec.InUnsafe;
-
// If some parent block was unsafe, we remain unsafe
even if this block
// isn't explicitly marked as such.
- ec.InUnsafe |= Unsafe;
+ using (ec.WithUnsafe (ec.InUnsafe | Unsafe)) {
+ //
+ // Compute the VariableMap's.
+ //
+ // Unfortunately, we don't know the type when
adding variables with
+ // AddVariable(), so we need to compute this
info here.
+ //
- //
- // Compute the VariableMap's.
- //
- // Unfortunately, we don't know the type when adding
variables with
- // AddVariable(), so we need to compute this info here.
- //
+ LocalInfo[] locals;
+ if (variables != null) {
+ foreach (LocalInfo li in
variables.Values)
+ li.Resolve (ec);
- LocalInfo[] locals;
- if (variables != null) {
- foreach (LocalInfo li in variables.Values)
- li.Resolve (ec);
+ locals = new LocalInfo
[variables.Count];
+ variables.Values.CopyTo (locals, 0);
+ } else
+ locals = new LocalInfo [0];
- locals = new LocalInfo [variables.Count];
- variables.Values.CopyTo (locals, 0);
- } else
- locals = new LocalInfo [0];
+ if (Parent != null)
+ local_map = new VariableMap
(Parent.LocalMap, locals);
+ else
+ local_map = new VariableMap (locals);
- if (Parent != null)
- local_map = new VariableMap (Parent.LocalMap,
locals);
- else
- local_map = new VariableMap (locals);
+ param_map = new VariableMap (ip);
+ flags |= Flags.VariablesInitialized;
- param_map = new VariableMap (ip);
- flags |= Flags.VariablesInitialized;
+ //
+ // Process this block variables
+ //
+ if (variables != null) {
+ using (ec.WithCheckState
(ec.CheckState, (flags & Flags.Unchecked) == 0)) {
+ foreach (DictionaryEntry de in
variables) {
+ string name = (string)
de.Key;
+ LocalInfo vi =
(LocalInfo) de.Value;
- //
- // Process this block variables
- //
- if (variables != null) {
- using (ec.WithCheckState (ec.CheckState, (flags
& Flags.Unchecked) == 0)) {
- foreach (DictionaryEntry de in
variables) {
- string name = (string) de.Key;
- LocalInfo vi = (LocalInfo)
de.Value;
-
- if (vi.VariableType == null)
- continue;
+ if (vi.VariableType ==
null)
+ continue;
- Type variable_type =
vi.VariableType;
+ Type variable_type =
vi.VariableType;
- if (variable_type.IsPointer) {
- //
- // Am not really
convinced that this test is required (Microsoft does it)
- // but the fact is that
you would not be able to use the pointer variable
- // *anyways*
- //
- if
(!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),
-
vi.Location))
+ if
(variable_type.IsPointer) {
+ //
+ // Am not
really convinced that this test is required (Microsoft does it)
+ // but the fact
is that you would not be able to use the pointer variable
+ // *anyways*
+ //
+ if
(!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),
+
vi.Location))
+
continue;
+ }
+
+ if (constants == null)
continue;
- }
- if (constants == null)
- continue;
+ Expression cv =
(Expression) constants [name];
+ if (cv == null)
+ continue;
- Expression cv = (Expression)
constants [name];
- if (cv == null)
- continue;
+ // Don't let 'const int
Foo = Foo;' succeed.
+ // Removing the name
from 'constants' ensures that we get a LocalVariableReference below,
+ // which in turn causes
the 'must be constant' error to be triggered.
+ constants.Remove (name);
- // Don't let 'const int Foo =
Foo;' succeed.
- // Removing the name from
'constants' ensures that we get a LocalVariableReference below,
- // which in turn causes the
'must be constant' error to be triggered.
- constants.Remove (name);
+ ec.CurrentBlock = this;
+ Expression e =
cv.Resolve (ec);
+ if (e == null)
+ continue;
- ec.CurrentBlock = this;
- Expression e = cv.Resolve (ec);
- if (e == null)
- continue;
+ Constant ce = e as
Constant;
+ if (ce == null) {
+
Const.Error_ExpressionMustBeConstant (variable_type, vi.Location, name);
+ continue;
+ }
- Constant ce = e as Constant;
- if (ce == null) {
-
Const.Error_ExpressionMustBeConstant (variable_type, vi.Location, name);
- continue;
- }
+ e = ce.ToType
(variable_type, vi.Location);
+ if (e == null)
+ continue;
- e = ce.ToType (variable_type,
vi.Location);
- if (e == null)
- continue;
+ if
(!variable_type.IsValueType && variable_type != TypeManager.string_type &&
!ce.IsDefaultValue) {
+
Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
+ continue;
+ }
- if (!variable_type.IsValueType
&& variable_type != TypeManager.string_type && !ce.IsDefaultValue) {
-
Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
- continue;
+ constants.Add (name, e);
+ vi.IsConstant = true;
}
-
- constants.Add (name, e);
- vi.IsConstant = true;
}
}
- }
- //
- // Now, handle the children
- //
- if (children != null) {
- foreach (Block b in children)
- b.ResolveMeta (toplevel, ec, ip);
+ //
+ // Now, handle the children
+ //
+ if (children != null) {
+ foreach (Block b in children)
+ b.ResolveMeta (toplevel, ec,
ip);
+ }
}
- ec.InUnsafe = old_unsafe;
}
//
@@ -3232,23 +3229,14 @@
public override bool Resolve (EmitContext ec)
{
- bool previous_state = ec.InUnsafe;
- bool val;
-
- ec.InUnsafe = true;
- val = Block.Resolve (ec);
- ec.InUnsafe = previous_state;
-
- return val;
+ using (ec.WithUnsafe (true))
+ return Block.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
{
- bool previous_state = ec.InUnsafe;
-
- ec.InUnsafe = true;
- Block.Emit (ec);
- ec.InUnsafe = previous_state;
+ using (ec.WithUnsafe (true))
+ Block.Emit (ec);
}
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches