/// </summary>
public abstract class TypeContainer : DeclSpace, IMemberContainer {
+ protected class CircularDepException: Exception
+ {
+ public TypeContainer Container;
+ public CircularDepException (TypeContainer tc)
+ {
+ Container = tc;
+ }
+ }
+
public class MemberCoreArrayList: ArrayList
{
/// <summary>
MemberCache member_cache;
public const string DefaultIndexerName = "Item";
+
+ // This is used to catch recursive definitions in declarations.
+ protected bool InTransit;
public TypeContainer (NamespaceEntry ns, TypeContainer parent, MemberName name,
Attributes attrs, Kind kind, Location l)
public abstract PendingImplementation GetPendingImplementations ();
- TypeExpr[] GetPartialBases (out TypeExpr base_class, out bool error)
+ TypeExpr[] GetPartialBases (out TypeExpr base_class)
{
ArrayList ifaces = new ArrayList ();
TypeExpr new_base_class;
TypeExpr[] new_ifaces;
- new_ifaces = part.GetClassBases (out new_base_class, out error);
- if (error)
+ new_ifaces = part.GetClassBases (out new_base_class);
+ if (new_ifaces == null && base_type != null)
return null;
if ((base_class != null) && (new_base_class != null) &&
if (!Location.IsNull (base_loc))
Report.LocationOfPreviousError (base_loc);
- error = true;
return null;
}
}
}
- error = false;
-
TypeExpr[] retval = new TypeExpr [ifaces.Count];
ifaces.CopyTo (retval, 0);
return retval;
}
- TypeExpr[] GetNormalBases (out TypeExpr base_class, out bool error)
+ TypeExpr[] GetNormalBases (out TypeExpr base_class)
{
base_class = null;
(Expression) Bases [0], false, Location);
if (name == null){
- error = true;
return null;
}
for (i = start, j = 0; i < count; i++, j++){
TypeExpr resolved = ResolveBaseTypeExpr ((Expression) Bases [i], false, Location);
if (resolved == null) {
- error = true;
return null;
}
ifaces [j] = resolved;
}
- error = false;
return ifaces;
}
/// The @base_class argument is set to the base object or null
/// if this is `System.Object'.
/// </summary>
- TypeExpr [] GetClassBases (out TypeExpr base_class, out bool error)
+ TypeExpr [] GetClassBases (out TypeExpr base_class)
{
int i;
- error = false;
-
TypeExpr[] ifaces;
if (parts != null)
- ifaces = GetPartialBases (out base_class, out error);
+ ifaces = GetPartialBases (out base_class);
else if (Bases == null){
base_class = null;
return null;
} else
- ifaces = GetNormalBases (out base_class, out error);
+ ifaces = GetNormalBases (out base_class);
- if (error)
+ if (ifaces == null)
return null;
if ((base_class != null) && (Kind == Kind.Class)){
if (base_class.Type.IsArray || base_class.Type.IsPointer) {
Report.Error (1521, base_class.Location, "Invalid base type");
- error = true;
return null;
}
if (base_class.IsSealed){
- error = true;
Report.SymbolRelatedToPreviousError (base_class.Type);
if (base_class.Type.IsAbstract) {
Report.Error (709, Location, "'{0}': Cannot derive from static class", GetSignatureForError ());
Report.Error (644, Location,
"`{0}' cannot inherit from special class `{1}'",
Name, base_class.Name);
- error = true;
return null;
}
TypeExpr iface = (TypeExpr) ifaces [i];
if (!iface.IsInterface) {
- error = true;
if (Kind != Kind.Class) {
- string what = Kind == Kind.Struct ? "Struct" : "Interface";
-
- Report.Error (527, Location,
- "In {0} `{1}', type `{2}' is not "+
- "an interface", what, Name, iface.Name);
+ // TODO: location of symbol related ....
+ Error_TypeInListIsNotInterface (Location, iface.FullName);
}
else if (base_class != null)
Report.Error (1721, Location,
"In Class `{0}', `{1}' is not " +
"an interface, a base class must be listed first", Name, iface.Name);
}
- continue;
+ return null;
}
for (int x = 0; x < i; x++) {
Report.Error (528, Location,
"`{0}' is already listed in " +
"interface list", iface.Name);
- error = true;
+ return null;
}
}
"interface `{0}' is less accessible " +
"than interface `{1}'", iface.Name,
Name);
- error = true;
+ return null;
}
}
-
- if (error)
- return null;
-
return ifaces;
}
- bool error = false;
-
+ protected void Error_TypeInListIsNotInterface (Location loc, string type)
+ {
+ Report.Error (527, loc, "'{0}': type in interface list is not an interface", type);
+ }
+
//
// Defines the type in the appropriate ModuleBuilder or TypeBuilder.
//
{
if (TypeBuilder != null)
return TypeBuilder;
-
- if (error)
- return null;
-
- if (InTransit) {
- Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
- error = true;
- return null;
- }
InTransit = true;
- TypeExpr[] iface_exprs = GetClassBases (out base_type, out error);
- if (error)
+ TypeExpr[] iface_exprs = GetClassBases (out base_type);
+ if (iface_exprs == null && base_type != null) {
+ InTransit = false;
return null;
+ }
if (base_type == null) {
if (Kind == Kind.Class){
// However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null.
ptype = base_type.ResolveType (TypeResolveEmitContext);
if (ptype == null) {
- error = true;
+ InTransit = false;
return null;
}
}
try {
if (IsTopLevel){
if (TypeManager.NamespaceClash (Name, Location)) {
- error = true;
+ InTransit = false;
return null;
}
} else {
TypeBuilder builder = Parent.TypeBuilder;
- if (builder == null)
+ if (builder == null) {
+ InTransit = false;
return null;
+ }
TypeBuilder = builder.DefineNestedType (
Basename, type_attributes, ptype, null);
}
catch (ArgumentException) {
Report.RuntimeMissingSupport (Location, "static classes");
+ InTransit = false;
return null;
}
TypeResolveEmitContext.ContainerType = TypeBuilder;
ifaces = TypeManager.ExpandInterfaces (TypeResolveEmitContext, iface_exprs);
if (ifaces == null) {
- error = true;
+ InTransit = false;
return null;
}
if (!(this is Iterator))
RootContext.RegisterOrder (this);
+ InTransit = false;
+
if (!DefineNestedTypes ()) {
- error = true;
return null;
}
- InTransit = false;
return TypeBuilder;
}
Modifiers.SEALED |
Modifiers.UNSAFE;
+ bool WasTransitError;
+
public Class (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
Attributes attrs, Location l)
: base (ns, parent, name, attrs, Kind.Class, l)
public override TypeBuilder DefineType()
{
+ if (InTransit) {
+ if (WasTransitError)
+ return null;
+ throw new CircularDepException (this);
+ }
+
if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
Report.Error (418, Location, "'{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
return null;
int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
ModFlags = Modifiers.Check (AllowedModifiersProp, ModFlags, accmods, Location);
- return base.DefineType ();
+ try {
+ return base.DefineType ();
+ }
+ catch (CircularDepException e) {
+ Report.SymbolRelatedToPreviousError (e.Container);
+ Report.Error (146, Location, "Circular base class dependency involving '{0}' and '{1}'",
+ GetSignatureForError (), e.Container.GetSignatureForError ());
+ WasTransitError = true;
+ return null;
+ }
}
/// Search for at least one defined condition in ConditionalAttribute of attribute class
return base.TypeAttr | DefaultTypeAttributes;
}
}
+
+ public override TypeBuilder DefineType()
+ {
+ if (InTransit) {
+ InTransit = false;
+ throw new CircularDepException (this);
+ }
+
+ try {
+ return base.DefineType ();
+ }
+ catch (CircularDepException e) {
+ InTransit = false;
+ Report.SymbolRelatedToPreviousError (this);
+ Error_TypeInListIsNotInterface (e.Container.Location, GetSignatureForError ());
+ return null;
+ }
+ }
}
/// <summary>
/// Interfaces
/// </summary>
public class Interface : TypeContainer, IMemberContainer {
+
+ bool WasTransitError;
+
/// <summary>
/// Modifiers allowed in a class declaration
/// </summary>
return base.TypeAttr | DefaultTypeAttributes;
}
}
+
+ public override TypeBuilder DefineType()
+ {
+ if (InTransit) {
+ if (WasTransitError)
+ return null;
+ throw new CircularDepException (this);
+ }
+
+ try {
+ return base.DefineType ();
+ }
+ catch (CircularDepException e) {
+ Report.SymbolRelatedToPreviousError (e.Container);
+ Report.Error (529, Location, "Inherited interface '{0}' causes a cycle in the interface hierarchy of '{1}'",
+ e.Container.GetSignatureForError (), GetSignatureForError ());
+ WasTransitError = true;
+ return null;
+ }
+ }
+
}
public abstract class MethodCore : MemberBase {
return false;
}
- //
- // Checks whether we're in a `catch' block.
- //
- public virtual bool InCatch ()
+ public virtual bool InTryWithCatch ()
{
if (Parent != null)
- return Parent.InCatch ();
- else
- return false;
- }
-
- //
- // Checks whether we're in a `finally' block.
- //
- public virtual bool InFinally (bool is_return)
- {
- if (!is_return &&
- ((Type == BranchingType.Loop) || (Type == BranchingType.Switch)))
- return false;
- else if (Parent != null)
- return Parent.InFinally (is_return);
- else
- return false;
+ return Parent.InTryWithCatch ();
+ return false;
}
public virtual bool InLoop ()
UsageVector finally_vector;
UsageVector finally_origins;
bool emit_finally;
- bool in_try;
public FlowBranchingException (FlowBranching parent,
ExceptionStatement stmt)
if (sibling.Type == SiblingType.Try) {
sibling.Next = catch_vectors;
catch_vectors = sibling;
- in_try = true;
} else if (sibling.Type == SiblingType.Catch) {
sibling.Next = catch_vectors;
catch_vectors = sibling;
- in_try = false;
} else if (sibling.Type == SiblingType.Finally) {
sibling.MergeFinallyOrigins (finally_origins);
finally_vector = sibling;
- in_try = false;
} else
throw new InvalidOperationException ();
return finally_vector == null;
}
- public override bool InCatch ()
+ public override bool InTryWithCatch ()
{
- return !in_try && (finally_vector == null);
- }
+ if (finally_vector == null) {
+ Try t = stmt as Try;
+ if (t != null && t.HasCatch)
+ return true;
+ }
- public override bool InFinally (bool is_return)
- {
- return finally_vector != null;
+ if (Parent != null)
+ return Parent.InTryWithCatch ();
+
+ return false;
}
public override bool BreakCrossesTryCatchBoundary ()
if (ec.CurrentBranching.InTryOrCatch (true)) {
ec.CurrentBranching.AddFinallyVector (vector);
in_exc = true;
- } else if (ec.CurrentBranching.InFinally (true)) {
+ } else if (ec.InFinally) {
Error (157, "Control can not leave the body of the finally block");
return false;
} else
return true;
}
- if (ec.CurrentBranching.InFinally (true)) {
- Error (724, "A throw statement with no argument is only allowed in a catch clause nested inside of the innermost catch clause");
+ if (!ec.InCatch) {
+ Error (156, "A throw statement with no arguments is not allowed outside of a catch clause");
return false;
}
- if (!ec.CurrentBranching.InCatch ()) {
- Error (156, "A throw statement with no argument is only allowed in a catch clause");
+ if (ec.InFinally) {
+ Error (724, "A throw statement with no argument is only allowed in a catch clause nested inside of the innermost catch clause");
return false;
}
return true;
if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
Error (139, "No enclosing loop or switch to continue to");
return false;
- } else if (ec.CurrentBranching.InFinally (false)) {
+ } else if (ec.InFinally && ec.CurrentBranching.BreakCrossesTryCatchBoundary()) {
Error (157, "Control can not leave the body of the finally block");
return false;
} else if (ec.CurrentBranching.InTryOrCatch (false))
if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
Error (139, "No enclosing loop to continue to");
return false;
- } else if (ec.CurrentBranching.InFinally (false)) {
+ } else if (ec.InFinally) {
Error (157, "Control can not leave the body of the finally block");
return false;
} else if (ec.CurrentBranching.InTryOrCatch (false))
public override bool Resolve (EmitContext ec)
{
- if (type_expr != null) {
- TypeExpr te = type_expr.ResolveAsTypeTerminal (ec, false);
- if (te == null)
- return false;
+ bool was_catch = ec.InCatch;
+ ec.InCatch = true;
+ try {
+ if (type_expr != null) {
+ TypeExpr te = type_expr.ResolveAsTypeTerminal (ec, false);
+ if (te == null)
+ return false;
- type = te.ResolveType (ec);
+ type = te.ResolveType (ec);
- CheckObsolete (type);
+ 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;
- }
- } else
- type = null;
+ 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;
+ }
+ } else
+ type = null;
- return Block.Resolve (ec);
+ return Block.Resolve (ec);
+ }
+ finally {
+ ec.InCatch = was_catch;
+ }
}
}
Fini, FlowBranching.SiblingType.Finally);
Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
-
+ bool was_finally = ec.InFinally;
+ ec.InFinally = true;
if (!Fini.Resolve (ec))
ok = false;
+ ec.InFinally = was_finally;
}
ResolveFinally (branching);
Fini.Emit (ec);
}
}
+
+ public bool HasCatch
+ {
+ get {
+ return General != null || Specific.Count > 0;
+ }
+ }
}
public class Using : ExceptionStatement {