+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Block.LookupLabel): Also lookup in implicit child blocks.
+ (Block.AddLabel): Call DoLookupLabel() to only search in the
+ current block.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * cfold.cs (ConstantFold.BinaryFold): Added special support for
+ comparing StringConstants and NullLiterals in Equality and Inequality.
+
+2004-04-28 Jackson Harper <jackson@ximian.com>
+
+ * driver.cs: Attempt to load referenced assemblies from the
+ GAC. This is the quick and dirty version of this method that
+ doesnt take into account versions and just takes the first
+ canidate found. Will be good enough for now as we will not have more
+ then one version installed into the GAC until I update this method.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.CheckStructCycles): New public
+ static method to check for cycles in the struct layout.
+
+ * rootcontext.cs (RootContext.PopulateTypes): Call
+ TypeManager.CheckStructCycles() for each TypeContainer.
+ [Note: We only need to visit each type once.]
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * constant.cs (StringConstant.Emit): Emit Ldnull if we're null.
+
+ * const.cs (Const.LookupConstantValue): Return a `bool' signalling
+ success and added `out object value'. Use a `bool resolved' field
+ to check whether we've already been called rather than
+ `ConstantValue != null' since this breaks for NullLiterals.
+
+2004-04-28 Raja R Harinath <rharinath@novell.com>
+
+ * driver.cs (Driver.MainDriver) [IsModuleOnly]: Open code the
+ setting of this flag, since the 'set' method may be non-public.
+
+2004-04-28 Raja R Harinath <rharinath@novell.com>
+
+ * flowanalysis.cs (FlowBranchingException.LookupLabel): Add a null
+ check on current_vector.Block.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (BaseAccess.CommonResolve): Don't allow `base' in
+ a field initializer. Fixes #56459.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (PropertyExpr.DoResolve/DoResolveLValue): Check whether
+ we're not attempting to use an indexer. Fixes #52154.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Return): Don't create a return label if we don't
+ need it; reverts my change from January 20th. Thanks to Ben
+ Maurer for this.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ According to the spec, `goto' can only leave a nested scope, but
+ never enter it.
+
+ * statement.cs (Block.LookupLabel): Only lookup in the current
+ block, don't recurse into parent or child blocks.
+ (Block.AddLabel): Check in parent and child blocks, report
+ CS0140/CS0158 if we find a duplicate.
+ (Block): Removed this indexer for label lookups.
+ (Goto.Resolve): Call LookupLabel() on our current FlowBranching;
+ this already does the error reporting for us.
+
+ * flowanalysis.cs
+ (FlowBranching.UsageVector.Block): New public variable; may be null.
+ (FlowBranching.CreateSibling): Added `Block' argument.
+ (FlowBranching.LookupLabel): New public virtual method. Lookup a
+ label for the target of a `goto' and check whether we're not
+ leaving a `finally'.
+
2004-04-27 Martin Baulig <martin@ximian.com>
* flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're
for a named field or property, implicity convert it to the correct
type.
+>>>>>>> 1.1450
2004-04-27 Raja R Harinath <rharinath@novell.com>
* statement.cs (Block.Block): Implicit blocks share
((BoolConstant) right).Value);
}
+ if (left is NullLiteral){
+ if (right is NullLiteral)
+ return new BoolConstant (true);
+ else if (right is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) right).Value == null);
+ } else if (right is NullLiteral){
+ if (left is NullLiteral)
+ return new BoolConstant (true);
+ else if (left is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) left).Value == null);
+ }
if (left is StringConstant && right is StringConstant){
return new BoolConstant (
((StringConstant) left).Value ==
((BoolConstant) left).Value !=
((BoolConstant) right).Value);
}
+ if (left is NullLiteral){
+ if (right is NullLiteral)
+ return new BoolConstant (false);
+ else if (right is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) right).Value != null);
+ } else if (right is NullLiteral){
+ if (left is NullLiteral)
+ return new BoolConstant (false);
+ else if (left is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) left).Value != null);
+ }
if (left is StringConstant && right is StringConstant){
return new BoolConstant (
((StringConstant) left).Value !=
public Expression Expr;
EmitContext const_ec;
+ bool resolved = false;
object ConstantValue = null;
Type type;
/// Looks up the value of a constant field. Defines it if it hasn't
/// already been. Similar to LookupEnumValue in spirit.
/// </summary>
- public object LookupConstantValue ()
+ public bool LookupConstantValue (out object value)
{
- if (ConstantValue != null)
- return ConstantValue;
+ if (resolved) {
+ value = ConstantValue;
+ return true;
+ }
if (in_transit) {
Report.Error (110, Location,
"The evaluation of the constant value for `" +
Name + "' involves a circular definition.");
- return null;
+ value = null;
+ return false;
}
in_transit = true;
//
// We might have cleared Expr ourselves in a recursive definition
//
- if (Expr == null)
- return null;
+ if (Expr == null){
+ value = null;
+ return false;
+ }
Expr = Expr.Resolve (const_ec);
if (Expr == null) {
if (errors == Report.Errors)
Report.Error (150, Location, "A constant value is expected");
- return null;
+ value = null;
+ return false;
}
Constant ce = Expr as Constant;
Expr = ac.TurnIntoConstant ();
if (Expr == null){
Report.Error (150, Location, "A constant value is expected");
- return null;
+ value = null;
+ return false;
}
} else {
if (errors == Report.Errors)
Report.Error (150, Location, "A constant value is expected");
- return null;
+ value = null;
+ return false;
}
}
if (type != ce.Type) {
ce = ChangeType (Location, ce, type);
- if (ce == null)
- return null;
+ if (ce == null){
+ value = null;
+ return false;
+ }
Expr = ce;
}
ConstantValue = ce.GetValue ();
FieldBuilder.SetConstant (ConstantValue);
if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
- return null;
+ throw new Exception ("Cannot register const value");
- return ConstantValue;
+ value = ConstantValue;
+ resolved = true;
+ return true;
}
/// </summary>
public override void Emit (TypeContainer parent)
{
- LookupConstantValue ();
+ object value;
+ LookupConstantValue (out value);
base.Emit (parent);
}
}
public override void Emit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldstr, Value);
+ if (Value == null)
+ ec.ig.Emit (OpCodes.Ldnull);
+ else
+ ec.ig.Emit (OpCodes.Ldstr, Value);
}
}
}
}
- static Assembly LoadAssemblyFromGac (string name)
+ static Assembly LoadAssemblyFromGac (string name)
{
PropertyInfo gac = typeof (System.Environment).GetProperty ("GacPath",
BindingFlags.Static|BindingFlags.NonPublic);
Environment.Exit (1);
}
- module_only.SetValue (CodeGen.Assembly.Builder, true, null);
+ MethodInfo set_method = module_only.GetSetMethod (true);
+ set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
}
TypeManager.AddModule (CodeGen.Module.Builder);
override public Expression DoResolve (EmitContext ec)
{
+ if (getter != null){
+ if (TypeManager.GetArgumentTypes (getter).Length != 0){
+ Report.Error (
+ 117, loc, "`{0}' does not contain a " +
+ "definition for `{1}'.", getter.DeclaringType,
+ Name);
+ return null;
+ }
+ }
+
if (getter == null){
//
// The following condition happens if the PropertyExpr was
return null;
}
+ if (TypeManager.GetArgumentTypes (setter).Length != 1){
+ Report.Error (
+ 117, loc, "`{0}' does not contain a " +
+ "definition for `{1}'.", getter.DeclaringType,
+ Name);
+ return null;
+ }
+
if (!InstanceResolve (ec))
return null;
Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
if (c != null) {
- object o = c.LookupConstantValue ();
- if (o == null)
+ object o;
+ if (!c.LookupConstantValue (out o))
return null;
-
+
object real_value = ((Constant) c.Expr).GetValue ();
return Constantify (real_value, fi.FieldType);
Error (1511, "Keyword base is not allowed in static method");
return null;
}
+
+ if (ec.IsFieldInitializer){
+ Error (1512, "Keyword base is not available in the current context");
+ return null;
+ }
member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type,
member, AllMemberTypes, AllBindingFlags,
// </summary>
public readonly Location Location;
+ // <summary>
+ // This is only valid for SwitchSection, Try, Catch and Finally.
+ // </summary>
+ public readonly Block Block;
+
// <summary>
// If this is true, then the usage vector has been modified and must be
// merged when we're done with this branching.
//
// Normally, you should not use any of these constructors.
//
- public UsageVector (SiblingType type, UsageVector parent, Location loc, int num_params, int num_locals)
+ public UsageVector (SiblingType type, UsageVector parent,
+ Block block, Location loc,
+ int num_params, int num_locals)
{
this.Type = type;
+ this.Block = block;
this.Location = loc;
this.InheritsFrom = parent;
this.CountParameters = num_params;
id = ++next_id;
}
- public UsageVector (SiblingType type, UsageVector parent, Location loc)
- : this (type, parent, loc, parent.CountParameters, parent.CountLocals)
+ public UsageVector (SiblingType type, UsageVector parent,
+ Block block, Location loc)
+ : this (type, parent, block, loc,
+ parent.CountParameters, parent.CountLocals)
{ }
public UsageVector (MyBitVector parameters, MyBitVector locals,
- Reachability reachability, Location loc)
+ Reachability reachability, Block block,
+ Location loc)
{
this.Type = SiblingType.Block;
this.Location = loc;
+ this.Block = block;
this.reachability = reachability;
this.parameters = parameters;
// </summary>
public UsageVector Clone ()
{
- UsageVector retval = new UsageVector (Type, null, Location, CountParameters, CountLocals);
+ UsageVector retval = new UsageVector (
+ Type, null, Block, Location,
+ CountParameters, CountLocals);
if (retval.locals != null)
retval.locals = locals.Clone ();
local_map = Block.LocalMap;
UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
- vector = new UsageVector (stype, parent_vector, loc, param_map.Length, local_map.Length);
-
-
+ vector = new UsageVector (
+ stype, parent_vector, Block, loc,
+ param_map.Length, local_map.Length);
} else {
param_map = Parent.param_map;
local_map = Parent.local_map;
- vector = new UsageVector (stype, Parent.CurrentUsageVector, loc);
+ vector = new UsageVector (
+ stype, Parent.CurrentUsageVector, null, loc);
}
AddSibling (vector);
// <summary>
// Creates a sibling of the current usage vector.
// </summary>
- public virtual void CreateSibling (SiblingType type)
+ public virtual void CreateSibling (Block block, SiblingType type)
{
- AddSibling (new UsageVector (type, Parent.CurrentUsageVector, Location));
+ UsageVector vector = new UsageVector (
+ type, Parent.CurrentUsageVector, block, Location);
+ AddSibling (vector);
Report.Debug (1, " CREATED SIBLING", CurrentUsageVector);
}
+ public void CreateSibling ()
+ {
+ CreateSibling (null, SiblingType.Conditional);
+ }
+
protected abstract void AddSibling (UsageVector uv);
+ public virtual LabeledStatement LookupLabel (string name, Location loc)
+ {
+ if (Parent != null)
+ return Parent.LookupLabel (name, loc);
+
+ Report.Error (
+ 159, loc,
+ "No such label `" + name + "' in this scope");
+ return null;
+ }
+
public abstract void Label (UsageVector origin_vectors);
// <summary>
Report.Debug (2, " MERGING SIBLINGS DONE", parameters, locals,
reachability, Infinite);
- return new UsageVector (parameters, locals, reachability, Location);
+ return new UsageVector (
+ parameters, locals, reachability, null, Location);
}
protected abstract UsageVector Merge ();
throw new NotSupportedException ();
UsageVector vector = new UsageVector (
- SiblingType.Conditional, null, Location, param_map.Length, local_map.Length);
+ SiblingType.Conditional, null, Block, Location,
+ param_map.Length, local_map.Length);
UsageVector result = vector.MergeChild (this);
sibling_list = sibling;
}
+ public override LabeledStatement LookupLabel (string name, Location loc)
+ {
+ if (Block == null)
+ return base.LookupLabel (name, loc);
+
+ LabeledStatement s = Block.LookupLabel (name);
+ if (s != null)
+ return s;
+
+ return base.LookupLabel (name, loc);
+ }
+
public override void Label (UsageVector origin_vectors)
{
if (!CurrentUsageVector.Reachability.IsUnreachable) {
finally_origins = vector;
}
+ public override LabeledStatement LookupLabel (string name, Location loc)
+ {
+ if (current_vector.Block == null)
+ return base.LookupLabel (name, loc);
+
+ LabeledStatement s = current_vector.Block.LookupLabel (name);
+ if (s != null)
+ return s;
+
+ if (finally_vector != null) {
+ Report.Error (
+ 157, loc, "Control can not leave the body " +
+ "of the finally block");
+ return null;
+ }
+
+ return base.LookupLabel (name, loc);
+ }
+
public override void Label (UsageVector origin_vectors)
{
CurrentUsageVector.MergeJumpOrigins (origin_vectors);
else
Report1530 (en.Location);
}
+
+ //
+ // Check for cycles in the struct layout
+ //
+ if (type_container_resolve_order != null){
+ Hashtable seen = new Hashtable ();
+ foreach (TypeContainer tc in type_container_resolve_order)
+ TypeManager.CheckStructCycles (tc, seen);
+ }
}
//
is_true_ret = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
+ ec.CurrentBranching.CreateSibling ();
if ((FalseStatement != null) && !FalseStatement.Resolve (ec))
ok = false;
ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
if (!infinite)
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
+ ec.CurrentBranching.CreateSibling ();
if (!Statement.Resolve (ec))
ok = false;
if (Expr != null) {
Expr.Emit (ec);
- if (in_exc || !ec.IsLastStatement)
+ if (in_exc)
ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
}
if (in_exc) {
ec.NeedReturnLabel ();
ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
- } else if (ec.IsLastStatement) {
- // If we are the last statement in a top-level block, simply
- // emit a `ret'.
- ec.ig.Emit (OpCodes.Ret);
} else {
- // Otherwise, we always create a return label and jump to
- // it.
- ec.NeedReturnLabel ();
- ec.ig.Emit (OpCodes.Br, ec.ReturnLabel);
+ ec.ig.Emit (OpCodes.Ret);
}
}
}
public override bool Resolve (EmitContext ec)
{
- label = block.LookupLabel (target);
- if (label == null){
- Report.Error (
- 159, loc,
- "No such label `" + target + "' in this scope");
+ label = ec.CurrentBranching.LookupLabel (target, loc);
+ if (label == null)
return false;
- }
// If this is a forward goto.
if (!label.IsDefined)
return switch_block.AddLabel (name, target, loc);
Block cur = this;
- while (cur != null && cur.Implicit) {
- if (cur.LookupLabel (name) != null) {
+ while (cur != null) {
+ if (cur.DoLookupLabel (name) != null) {
Report.Error (
140, loc, "The label '{0}' is a duplicate",
name);
return false;
}
+ if (!Implicit)
+ break;
+
cur = cur.Parent;
}
while (cur != null) {
- if (cur.LookupLabel (name) != null) {
+ if (cur.DoLookupLabel (name) != null) {
Report.Error (
158, loc,
"The label '{0}' shadows another label " +
return false;
}
+ if (children != null) {
+ foreach (Block b in children) {
+ LabeledStatement s = b.DoLookupLabel (name);
+ if (s == null)
+ continue;
+
+ Report.Error (
+ 158, s.Location,
+ "The label '{0}' shadows another " +
+ "label by the same name in a " +
+ "containing scope.",
+ name);
+ return false;
+ }
+ }
+
+
cur = cur.Parent;
}
public LabeledStatement LookupLabel (string name)
{
- Hashtable l = new Hashtable ();
-
- return LookupLabel (name, l);
+ LabeledStatement s = DoLookupLabel (name);
+ if (s != null)
+ return s;
+
+ if (children == null)
+ return null;
+
+ foreach (Block child in children) {
+ if (!child.Implicit)
+ continue;
+
+ s = child.LookupLabel (name);
+ if (s != null)
+ return s;
+ }
+
+ return null;
}
- //
- // Lookups a label in the current block, parents and children.
- // It skips during child recurssion on `source'
- //
- LabeledStatement LookupLabel (string name, Hashtable seen)
+ LabeledStatement DoLookupLabel (string name)
{
if (switch_block != null)
- return switch_block.LookupLabel (name, seen);
+ return switch_block.LookupLabel (name);
- if (seen [this] != null)
- return null;
-
- seen [this] = this;
-
if (labels != null)
if (labels.Contains (name))
return ((LabeledStatement) labels [name]);
- if (children != null){
- foreach (Block b in children){
- LabeledStatement s = b.LookupLabel (name, seen);
- if (s != null)
- return s;
- }
- }
-
- if (Parent != null)
- return Parent.LookupLabel (name, seen);
-
return null;
}
return e != null;
}
- /// <summary>
- /// Use to fetch the statement associated with this label
- /// </summary>
- public Statement this [string name] {
- get {
- return (Statement) labels [name];
- }
- }
-
Parameters parameters = null;
public Parameters Parameters {
get {
bool first = true;
foreach (SwitchSection ss in Sections){
if (!first)
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
+ ec.CurrentBranching.CreateSibling (
+ null, FlowBranching.SiblingType.SwitchSection);
else
first = false;
if (!got_default)
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
+ ec.CurrentBranching.CreateSibling (
+ null, FlowBranching.SiblingType.SwitchSection);
FlowBranching.Reachability reachability = ec.EndFlowBranching ();
ec.Switch = old_switch;
Report.Debug (1, "START OF CATCH BLOCKS", vector);
foreach (Catch c in Specific){
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
+ ec.CurrentBranching.CreateSibling (
+ c.Block, FlowBranching.SiblingType.Catch);
+
Report.Debug (1, "STARTED SIBLING FOR CATCH", ec.CurrentBranching);
if (c.Name != null) {
Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
if (General != null){
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
+ ec.CurrentBranching.CreateSibling (
+ General.Block, FlowBranching.SiblingType.Catch);
+
Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
if (!General.Resolve (ec))
if (Fini != null) {
if (ok)
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Finally);
+ ec.CurrentBranching.CreateSibling (
+ Fini, FlowBranching.SiblingType.Finally);
+
Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
if (!Fini.Resolve (ec))
bool ok = true;
ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
- ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
+ ec.CurrentBranching.CreateSibling ();
//
//
return false;
}
+ public static bool IsBuiltinType (TypeContainer tc)
+ {
+ return IsBuiltinType (tc.TypeBuilder);
+ }
+
//
// This is like IsBuiltinType, but lacks decimal_type, we should also clean up
// the pieces in the code where we use IsBuiltinType and special case decimal_type.
return true;
}
+ public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
+ {
+ Hashtable hash = new Hashtable ();
+ return CheckStructCycles (tc, seen, hash);
+ }
+
+ public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
+ Hashtable hash)
+ {
+ if (!(tc is Struct) || IsBuiltinType (tc))
+ return true;
+
+ //
+ // `seen' contains all types we've already visited.
+ //
+ if (seen.Contains (tc))
+ return true;
+ seen.Add (tc, null);
+
+ //
+ // `hash' contains all types in the current path.
+ //
+ hash.Add (tc, null);
+
+ if (tc.Fields == null)
+ return true;
+
+ foreach (Field field in tc.Fields) {
+ if (field.FieldBuilder.IsStatic)
+ continue;
+
+ Type ftype = field.FieldBuilder.FieldType;
+ TypeContainer ftc = LookupTypeContainer (ftype);
+ if (ftc == null)
+ continue;
+
+ if (hash.Contains (ftc)) {
+ Report.Error (523, tc.Location,
+ "Struct member `{0}.{1}' of type `{2}' " +
+ "causes a cycle in the struct layout",
+ tc.Name, field.Name, ftc.Name);
+ return false;
+ }
+
+ if (!CheckStructCycles (ftc, seen, hash))
+ return false;
+ }
+
+ return true;
+ }
+
/// <summary>
/// Given an array of interface types, expand and eliminate repeated ocurrences
/// of an interface.