**** Merged from HEAD ****
authorMartin Baulig <martin@novell.com>
Thu, 22 Jan 2004 04:32:09 +0000 (04:32 -0000)
committerMartin Baulig <martin@novell.com>
Thu, 22 Jan 2004 04:32:09 +0000 (04:32 -0000)
svn path=/trunk/mcs/; revision=22380

25 files changed:
mcs/gmcs/ChangeLog
mcs/gmcs/Makefile
mcs/gmcs/assign.cs
mcs/gmcs/attribute.cs
mcs/gmcs/class.cs
mcs/gmcs/codegen.cs
mcs/gmcs/const.cs
mcs/gmcs/convert.cs
mcs/gmcs/cs-parser.jay
mcs/gmcs/cs-tokenizer.cs
mcs/gmcs/decl.cs
mcs/gmcs/delegate.cs
mcs/gmcs/driver.cs
mcs/gmcs/ecore.cs
mcs/gmcs/enum.cs
mcs/gmcs/expression.cs
mcs/gmcs/flowanalysis.cs
mcs/gmcs/generic.cs
mcs/gmcs/interface.cs
mcs/gmcs/iterators.cs
mcs/gmcs/pending.cs
mcs/gmcs/rootcontext.cs
mcs/gmcs/statement.cs
mcs/gmcs/tree.cs
mcs/gmcs/typemanager.cs

index 137ecd0cc8683dd4283dbd4d9acf29df80d624d7..e69185b48424e9fe69ead577fad64d573aca699b 100755 (executable)
@@ -1,3 +1,342 @@
+2004-01-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldInfo.AddressOf): Revert patch from previous
+       #52730 bug, and instead compute correctly the need to use a
+       temporary variable when requesting an address based on the
+       static/instace modified of the field and the constructor.
+2004-01-21  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup in the current
+       class and namespace before looking up aliases.  Fixes #52517.
+
+2004-01-21  Martin Baulig  <martin@ximian.com>
+
+       * flowanalysis.cs (UsageVector.Merge): Allow variables being
+       assinged in a 'try'; fixes exception4.cs.
+
+2004-01-21  Marek Safar  <marek.safar@seznam.cz>
+        * class.cs : Implemented parameter-less constructor for TypeContainer
+        
+        * decl.cs: Attributes are now stored here. New property OptAttributes
+        
+        * delegate.cs, enum.cs, interface.cs: Removed attribute member.
+        
+        * rootcontext.cs, tree.cs: Now use parameter-less constructor of TypeContainer
+
+2004-01-21  Marek Safar  <marek.safar@seznam.cz>
+
+       * typemanager.cs (CSharpSignature): Now reports also inner class name.
+          (CSharpSignature): New method for indexer and property signature.
+
+2004-01-21  Marek Safar  <marek.safar@seznam.cz>
+
+       * pending.cs (IsVirtualFilter): Faster implementation.
+
+2004-01-21  Marek Safar  <marek.safar@seznam.cz>
+
+       * typemanager.cs: Avoid inclusion of same assembly more than once.
+
+2004-01-21  Marek Safar  <marek.safar@seznam.cz>
+
+       * cs-parser.jay: Fixed problem where the last assembly attribute
+          has been applied also to following declaration (class, struct, etc.)
+          
+2004-01-21  Marek Safar  <marek.safar@seznam.cz>
+
+       * class.cs: Added error CS0538, CS0539 reporting.
+        Fixed crash on Microsoft runtime when field type is void.
+
+       * cs-parser.jay: Added error CS0537 reporting.
+
+       * pending.cs: Added error CS0535 reporting.
+        Improved error report for errors CS0536, CS0534.
+
+2004-01-20  Miguel de Icaza  <miguel@ximian.com>
+
+       Merge a few bits from the Anonymous Method MCS tree.
+       
+       * statement.cs (ToplevelBlock): New class for toplevel methods,
+       will hold anonymous methods, lifted variables.
+
+       * cs-parser.jay: Create toplevel blocks for delegates and for
+       regular blocks of code. 
+
+2004-01-20  Martin Baulig  <martin@ximian.com>
+
+       * codegen.cs (EmitContext): Removed `InTry', `InCatch',
+       `InFinally', `InLoop', `TryCatchLevel', `LoopBeginTryCatchLevel'
+       and `NeedExplicitReturn'; added `IsLastStatement'.
+       (EmitContext.EmitTopBlock): Emit the explicit "ret" if we either
+       have a `ReturnLabel' or we're not unreachable.
+
+       * flowanalysis.cs (FlowBranching.MergeChild): Actually merge the
+       child's reachability; don't just override ours with it.  Fixes
+       #58058 (lluis's example).
+       (FlowBranching): Added public InTryOrCatch(), InCatch(),
+       InFinally(), InLoop(), InSwitch() and
+       BreakCrossesTryCatchBoundary() methods.
+
+       * statement.cs (Return): Do all error checking in Resolve().
+       Unless we are the last statement in a top-level block, always
+       create a return label and jump to it.
+       (Break, Continue): Do all error checking in Resolve(); also make
+       sure we aren't leaving a `finally'.
+       (Block.DoEmit): Set `ec.IsLastStatement' when emitting the last
+       statement in a top-level block.
+       (Block.Flags): Added `IsDestructor'.
+       (Block.IsDestructor): New public property.
+
+2004-01-20  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (Break.DoEmit): Set ec.NeedExplicitReturn; fixes #52427.
+
+2004-01-20  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (Statement.ResolveUnreachable): New public method.
+       (If, While): Do the dead-code elimination in Resolve(), not in Emit().
+       (Block.Resolve): Resolve unreachable statements.
+
+2004-01-19 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * expression.cs: We need to fix the case where we do
+       not have a temp variable here.
+
+       * assign.cs: Only expression compound assignments need
+       temporary variables.
+
+2004-01-19 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * flowanalysis.cs: Reduce memory allocation in a few ways:
+         - A block with no variables should not allocate a bit
+           vector for itself.
+         - A method with no out parameters does not need any tracking
+           for assignment of the parameters, so we need not allocate
+           any data for it.
+         - The arrays:
+               public readonly Type[] VariableTypes;
+               public readonly string[] VariableNames;
+           Are redundant. The data is already stored in the variable
+           map, so we need not allocate another array for it.
+         - We need to add alot of checks for if (params | locals) == null
+           due to the first two changes.
+
+2004-01-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr.AddressOf): For ValueTypes that do not
+       implement IMemoryLocation, we store a copy on a local variable and
+       take the address of it.  Patch from Benjamin Jemlich
+
+       * cs-parser.jay: Applied patch from Ben Maurer to the "type" rule
+       to use a special "type_name_expression" rule which reduces the
+       number of "QualifiedIdentifier" classes created, and instead
+       directly creates MemberAccess expressions.
+
+2004-01-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * convert.cs: Applied patch from Benjamin Jemlich (pcgod@gmx.net)
+       that fixes #52853.  Null literal assignment to ValueType
+
+       * class.cs (MethodData.Emit): Instead of checking the name of the
+       method to determine if its a destructor, create a new derived
+       class from Method called Destructor, and test for that.  
+
+       * cs-parser.jay: Create a Destructor object instead of a Method.  
+
+       Based on a fix from Benjamin Jemlich (pcgod@gmx.net)
+
+       Fixes: 52933
+       
+2004-01-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary.ResolveOperator): Perform an implicit
+       conversion from MethodGroups to their delegate types on the
+       Addition operation.
+
+       * delegate.cs: Introduce a new class DelegateCreation that is the
+       base class for `NewDelegate' and `ImplicitDelegateCreation',
+       factor some code in here.
+
+       * convert.cs (Convert.ImplicitConversionStandard): Add an implicit
+       conversion from MethodGroups to compatible delegate types. 
+
+       * ecore.cs (Expression.Resolve): Do not flag error 654
+       (Methodgroupd needs parenthesis) if running on the V2 compiler, as
+       we allow conversions from MethodGroups to delegate types now.
+       
+       * assign.cs (Assign.DoResolve): Do not flag errors on methodgroup
+       assignments in v2 either.
+
+2004-01-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr.AddressOf): Fix generated IL for accessing
+       static read-only fields in ctors.
+
+       Applied patch from Benjamin Jemlich 
+
+       * expression.cs (UnaryMutator): Avoid leaking local variables. 
+       
+2004-01-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs (IsCastToken): Allow the various native types
+       here to return true, as they can be used like this:
+
+               (XXX) int.MEMBER ()
+
+       Fixed 49836 and all the other dups
+       
+2004-01-09  Zoltan Varga  <vargaz@freemail.hu>
+
+       * driver.cs: Implement /win32res and /win32icon.
+
+2004-01-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add a rule to improve error handling for the
+       common mistake of placing modifiers after the type.
+
+2004-01-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (interface_event_declaration): Catch
+       initialization of events on interfaces, and report cs0068
+
+       * cs-parser.jay (interface_event_declaration): Catch
+       initialization of events. 
+
+       * ecore.cs: Better report missing constructors.
+       
+       * expression.cs (Binary.ResolveOperator): My previous bug fix had
+       the error reporting done in the wrong place.  Fix.
+
+       * expression.cs (Binary.ResolveOperator): Catch the 
+       operator + (E x, E y) error earlier, and later allow for implicit
+       conversions in operator +/- (E e, U x) from U to the underlying
+       type of E.
+
+       * class.cs (TypeContainer.DefineDefaultConstructor): Fix bug
+       52596, if the container class is abstract, the default constructor
+       is protected otherwise its public (before, we were always public).
+
+       * statement.cs (Fixed.Resolve): Catch a couple more errors in the
+       fixed statement.
+
+       (Using.EmitLocalVariableDecls): Applied patch from Benjamin
+       Jemlich that fixes bug #52597, MCS was generating invalid code for
+       idisposable structs.   Thanks to Ben for following up with this
+       bug as well.
+       
+2004-01-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Allow assemblies without code to be generated, fixes
+       52230.
+
+2004-01-07  Nick Drochak <ndrochak@gol.com>
+
+       * attribute.cs: Remove unneeded catch variables. Eliminates a warning.
+
+2004-01-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add rules to improve error reporting if fields or
+       methods are declared at the namespace level (error 116)
+
+       * Add rules to catch event add/remove
+
+2004-01-04  David Sheldon <dave-mono@earth.li>
+
+  * expression.cs: Added matching ")" to error message for 
+  CS0077
+
+2004-01-03 Todd Berman <tberman@gentoo.org>
+       
+       * ecore.cs, attribute.cs:
+       Applying fix from #52429.
+
+2004-01-03 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * ecore.cs, expression.cs, statement.cs:
+       Total rewrite of how we handle branching. We
+       now handle complex boolean expressions with fewer
+       jumps. As well if (x == 0) no longer emits a ceq.
+
+       if (x is Foo) is much faster now, because we generate
+       better code.
+
+       Overall, we get a pretty big improvement on our benchmark
+       tests. The code we generate is smaller and more readable.
+
+       I did a full two-stage bootstrap. The patch was reviewed
+       by Martin and Miguel.
+
+2004-01-03 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * cs-parser.jay: Make primary_expression not take a QI.
+       we dont need this because the member_access rule covers
+       us here. So we replace the rule with just IDENTIFIER.
+
+       This has two good effects. First, we remove a s/r conflict.
+       Second, we allocate many fewer QualifiedIdentifier objects.
+
+2004-01-03 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * attribute.cs: Handle MarshalAs attributes as pseudo, and
+       set the correct information via SRE. This prevents
+       hanging on the MS runtime. Fixes #29374.
+
+2004-01-03 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * convert.cs: correctly handle conversions to value types
+       from Enum and ValueType as unboxing conversions.
+
+       Fixes bug #52569. Patch by Benjamin Jemlich.
+
+2004-01-02  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (BetterConversion): Prefer int -> uint
+       over int -> ulong (csc's behaviour). This fixed bug #52046.
+
+2004-01-02 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * decl.cs (MemberCache.FindMembers): now returns a
+       MemberInfo [].
+
+       * typemanager.cs: In general, go with with ^^.
+       (CopyNewMethods): take an IList.
+       (RealMemberLookup): Only allocate an arraylist
+       if we copy from two sets of methods.
+
+       This change basically does two things:
+       1) Fewer array lists allocated due to CopyNewMethods.
+       2) the explicit cast in MemberList costed ALOT.
+
+2004-01-02  Zoltan Varga  <vargaz@freemail.hu>
+
+       * cs-tokenizer.cs (consume_identifier) driver.cs: Cache identifiers in
+       a hashtable to avoid needless string allocations when an identifier is
+       used more than once (the common case).
+
+2004-01-01 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * pending.cs: MS's TypeBuilder.GetInterfaces ()
+       is broken, it will not return anything. So, we
+       have to use the information we have in mcs to
+       do the task.
+
+       * typemanager.cs: Add a cache for GetInterfaces,
+       since this will now be used more often (due to ^^)
+
+       (GetExplicitInterfaces) New method that gets the
+       declared, not effective, interfaces on a type
+       builder (eg, if you have interface IFoo, interface
+       IBar, Foo : IFoo, Bar : Foo, IBar, GetExplInt (Bar) ==
+       { IBar }.
+
+       This patch makes MCS able to bootstrap itself on
+       Windows again.
+
+2004-01-01 Ben Maurer  <bmaurer@users.sourceforge.net>
+
+       * expression.cs: Remove the Nop's that Miguel put
+       in by mistake.
+
 2003-12-31 Ben Maurer  <bmaurer@users.sourceforge.net>
 
        * report.cs, codegen.cs: Give the real stack trace to
index 055cbfa5d049abf8c58c2f3f902bc1f0890412ea..97b722ba14247b1844754d0fafefb8669fbf7c2c 100644 (file)
@@ -105,6 +105,11 @@ do-time : mcs.exe
        @ rm -f ../class/lib/mscorlib.dll
        @ (cd ../class/corlib ; make BOOTSTRAP_MCS="$(FRIENDLY_TIME) mono ../../mcs/mcs.exe" > /dev/null ) || (echo FAILED; exit 1)
 
+do-corlib:
+       @ echo -n "corlib:  "
+       @ rm -f ../class/lib/mscorlib.dll
+       @ (cd ../class/corlib ; make BOOTSTRAP_MCS="$(FRIENDLY_TIME) mono ../../mcs/mcs.exe" > /dev/null ) || (echo FAILED; exit 1)
+
 PROFILER=default
 
 profile : mcs.exe
index dae00366584056cbf497f1f09ac838a78a6414b8..ff3521059bf7b1837cff438f5eabb38ba5682fe7 100755 (executable)
@@ -262,9 +262,10 @@ namespace Mono.CSharp {
                        if ((source.eclass == ExprClass.Type) && (source is TypeExpr)) {
                                source.Error_UnexpectedKind ("variable or value");
                                return null;
-                       } else if (source is MethodGroupExpr){
+                       } else if (!RootContext.V2 && (source is MethodGroupExpr)){
                                ((MethodGroupExpr) source).ReportUsageError ();
                                return null;
+
                        }
 
                        if (target_type == source_type)
@@ -378,10 +379,8 @@ namespace Mono.CSharp {
                        // 
                        IAssignMethod am = (IAssignMethod) target;
                        
-                       if (this is CompoundAssign){
+                       if (this is CompoundAssign)
                                am.CacheTemporaries (ec);
-                               use_temporaries = true;
-                       }
 
                        if (!is_statement)
                                use_temporaries = true;
index 7667150fe489cfee96d440931ca38052a8b7c05d..0605282a645c22cdd4724f99349b95e47995031e 100644 (file)
@@ -150,6 +150,12 @@ namespace Mono.CSharp {
                                result =  ((ArrayCreation) e).EncodeAsAttribute ();\r
                                if (result != null)\r
                                        return true;\r
+                       } else if (e is EmptyCast) {\r
+                               result = e;\r
+                               if (((EmptyCast) e).Child is Constant) {\r
+                                       result = ((Constant) ((EmptyCast)e).Child).GetValue();\r
+                               }\r
+                               return true;\r
                        }\r
 \r
                        result = null;\r
@@ -306,6 +312,8 @@ namespace Mono.CSharp {
                                                \r
                                        } else if (e is TypeOf) {\r
                                                prop_values.Add (((TypeOf) e).TypeArg);\r
+                                       } else if (e is ArrayCreation) {\r
+                                               prop_values.Add (((ArrayCreation) e).EncodeAsAttribute());\r
                                        } else {\r
                                                Error_AttributeArgumentNotValid (Location);\r
                                                return null;\r
@@ -776,27 +784,37 @@ namespace Mono.CSharp {
 \r
                static UnmanagedMarshal GetMarshal (Attribute a)\r
                 {\r
-                       UnmanagedMarshal marshal;\r
-\r
-                       if (a.UnmanagedType == UnmanagedType.CustomMarshaler) {\r
+                       object o = GetFieldValue (a, "ArraySubType");\r
+                       UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;\r
+                       switch (a.UnmanagedType) {\r
+                       case UnmanagedType.CustomMarshaler:\r
                                MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",\r
                                                                        BindingFlags.Static | BindingFlags.Public);\r
-                               if (define_custom == null) {\r
+                               if (define_custom == null)\r
                                        return null;\r
-                               }\r
-                               object[] args = new object [4];\r
+\r
+                               object [] args = new object [4];\r
                                args [0] = GetFieldValue (a, "MarshalTypeRef");\r
                                args [1] = GetFieldValue (a, "MarshalCookie");\r
                                args [2] = GetFieldValue (a, "MarshalType");\r
                                args [3] = Guid.Empty;\r
-                               marshal = (UnmanagedMarshal) define_custom.Invoke (null, args);\r
-                       /*\r
-                        * need to special case other special marshal types\r
-                        */\r
-                       } else {\r
-                               marshal = UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);\r
+                               return (UnmanagedMarshal) define_custom.Invoke (null, args);\r
+\r
+                       case UnmanagedType.LPArray:                             \r
+                               return UnmanagedMarshal.DefineLPArray (array_sub_type);\r
+\r
+                       case UnmanagedType.SafeArray:\r
+                               return UnmanagedMarshal.DefineSafeArray (array_sub_type);\r
+\r
+                       case UnmanagedType.ByValArray:\r
+                               return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue (a, "SizeConst"));\r
+\r
+                       case UnmanagedType.ByValTStr:\r
+                               return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue (a, "SizeConst"));\r
+\r
+                       default:\r
+                               return UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);\r
                        }\r
-                       return marshal;\r
                }\r
 \r
                /// <summary>\r
@@ -867,7 +885,18 @@ namespace Mono.CSharp {
                                        } else if (kind is Constructor) {\r
                                                ((ConstructorBuilder) builder).SetCustomAttribute (cb);\r
                                        } else if (kind is Field) {\r
-                                               ((FieldBuilder) builder).SetCustomAttribute (cb);\r
+                                               if (attr_type == TypeManager.marshal_as_attr_type) {\r
+                                                       UnmanagedMarshal marshal = GetMarshal (a);\r
+                                                       if (marshal == null) {\r
+                                                               Report.Warning (-24, loc,\r
+                                                                       "The Microsoft Runtime cannot set this marshal info. " +\r
+                                                                       "Please use the Mono runtime instead.");\r
+                                                       } else {\r
+                                                               ((FieldBuilder) builder).SetMarshal (marshal);\r
+                                                       }\r
+                                               } else { \r
+                                                       ((FieldBuilder) builder).SetCustomAttribute (cb);\r
+                                               }\r
                                        } else if (kind is Property || kind is Indexer ||\r
                                                   kind is InterfaceProperty || kind is InterfaceIndexer) {\r
                                                ((PropertyBuilder) builder).SetCustomAttribute (cb);\r
@@ -927,7 +956,7 @@ namespace Mono.CSharp {
 \r
                                                try {\r
                                                        ((TypeBuilder) builder).SetCustomAttribute (cb);\r
-                                               } catch (System.ArgumentException e) {\r
+                                               } catch (System.ArgumentException) {\r
                                                        Report.Warning (\r
                                                                -21, loc,\r
                                                "The CharSet named property on StructLayout\n"+\r
@@ -943,7 +972,7 @@ namespace Mono.CSharp {
                                                }\r
                                                try {\r
                                                        ((TypeBuilder) builder).SetCustomAttribute (cb);\r
-                                               } catch (System.ArgumentException e) {\r
+                                               } catch (System.ArgumentException) {\r
                                                        Report.Warning (\r
                                                                -21, loc,\r
                                                "The CharSet named property on StructLayout\n"+\r
index 92e9191e0de7a3e31c98b499ff7d410091fffde3..8e760870377f9b123ab646dd9172e27a92ac749e 100755 (executable)
@@ -113,9 +113,6 @@ namespace Mono.CSharp {
 
                ArrayList type_bases;
 
-               // Attributes for this type
-               protected Attributes attributes;
-
                // Information in the case we are an attribute type
 
                public AttributeTargets Targets = AttributeTargets.All;
@@ -134,8 +131,12 @@ namespace Mono.CSharp {
                //
                public string IndexerName;
 
-               public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Location l)
-                       : base (ns, parent, name, l)
+               public TypeContainer ():
+                       this (null, null, "", null, new Location (-1)) {
+               }
+
+               public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
+                       : base (ns, parent, name, attrs, l)
                {
                        types = new ArrayList ();
 
@@ -499,12 +500,6 @@ namespace Mono.CSharp {
                        }
                }
                
-               public Attributes OptAttributes {
-                       get {
-                               return attributes;
-                       }
-               }
-               
                public bool HaveStaticConstructor {
                        get {
                                return have_static_constructor;
@@ -573,11 +568,17 @@ namespace Mono.CSharp {
                        if (is_static)
                                mods = Modifiers.STATIC;
 
+                       //
+                       // If the class is abstract, the default constructor is protected
+                       //
+                       if ((ModFlags & Modifiers.ABSTRACT) != 0)
+                               mods |= Modifiers.PROTECTED;
+                       
                        c.ModFlags = mods;
 
                        AddConstructor (c);
                        
-                       c.Block = new Block (null);
+                       c.Block = new ToplevelBlock (null, Location);
                        
                }
 
@@ -1786,7 +1787,7 @@ namespace Mono.CSharp {
                        default_constructor = null;
                        default_static_constructor = null;
                        type_bases = null;
-                       attributes = null;
+                       OptAttributes = null;
                        ifaces = null;
                        parent_container = null;
                        member_cache = null;
@@ -1943,11 +1944,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
-               {
-                       Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
-               }
-
                //
                // IMemberContainer
                //
@@ -2176,7 +2172,7 @@ namespace Mono.CSharp {
                        Modifiers.UNSAFE;
 
                public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
-                       : base (ns, parent, name, l)
+                       : base (ns, parent, name, attrs, l)
                {
                        int accmods;
 
@@ -2186,7 +2182,6 @@ namespace Mono.CSharp {
                                accmods = Modifiers.PRIVATE;
 
                        this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
-                       this.attributes = attrs;
                }
 
                //
@@ -2213,7 +2208,7 @@ namespace Mono.CSharp {
                        Modifiers.PRIVATE;
 
                public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
-                       : base (ns, parent, name, l)
+                       : base (ns, parent, name, attrs, l)
                {
                        int accmods;
                        
@@ -2225,8 +2220,6 @@ namespace Mono.CSharp {
                        this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
 
                        this.ModFlags |= Modifiers.SEALED;
-                       this.attributes = attrs;
-                       
                }
 
                //
@@ -2732,7 +2725,7 @@ namespace Mono.CSharp {
                        Expression parent_constructor_group;
                        Type t;
 
-                       ec.CurrentBlock = new Block (null, Block.Flags.Implicit, parameters);
+                       ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
 
                        if (argument_list != null){
                                foreach (Argument a in argument_list){
@@ -2808,7 +2801,6 @@ namespace Mono.CSharp {
        public class Constructor : MethodCore {
                public ConstructorBuilder ConstructorBuilder;
                public ConstructorInitializer Initializer;
-               new public Attributes OptAttributes;
 
                // <summary>
                //   Modifiers allowed for a constructor.
@@ -3287,8 +3279,7 @@ namespace Mono.CSharp {
                                                member.InterfaceType, name, ReturnType, ParameterTypes);
 
                                if (member.InterfaceType != null && implementing == null){
-                                       TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
-                                               Location, name);
+                                       Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
                                        return false;
                                }
                        }
@@ -3503,7 +3494,7 @@ namespace Mono.CSharp {
                        //
                        // FIXME: This code generates buggy code
                        //
-                       if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
+                       if (member is Destructor)
                                EmitDestructor (ec, block);
                        else {
                                SymbolWriter sw = CodeGen.SymbolWriter;
@@ -3525,18 +3516,15 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        Label finish = ig.DefineLabel ();
-                       bool old_in_try = ec.InTry;
+
+                       block.SetDestructor ();
                        
                        ig.BeginExceptionBlock ();
-                       ec.InTry = true;
                        ec.ReturnLabel = finish;
                        ec.HasReturnLabel = true;
                        ec.EmitTopBlock (block, null, Location);
-                       ec.InTry = old_in_try;
                        
                        // ig.MarkLabel (finish);
-                       bool old_in_finally = ec.InFinally;
-                       ec.InFinally = true;
                        ig.BeginFinallyBlock ();
                        
                        if (ec.ContainerType.BaseType != null) {
@@ -3551,7 +3539,6 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
                                }
                        }
-                       ec.InFinally = old_in_finally;
                        
                        ig.EndExceptionBlock ();
                        //ig.MarkLabel (ec.ReturnLabel);
@@ -3559,9 +3546,17 @@ namespace Mono.CSharp {
                }
        }
 
+       public class Destructor : Method {
+
+               public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
+                                  Parameters parameters, Attributes attrs, Location l)
+                       : base (ds, return_type, mod, name, parameters, attrs, l)
+               { }
+
+       }
+       
        abstract public class MemberBase : MemberCore {
                public Expression Type;
-               public readonly Attributes OptAttributes;
 
                protected MethodAttributes flags;
 
@@ -3608,12 +3603,11 @@ namespace Mono.CSharp {
                //
                protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
                                      Attributes attrs, Location loc)
-                       : base (name, loc)
+                       : base (name, attrs, loc)
                {
                        explicit_mod_flags = mod;
                        Type = type;
                        ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
-                       OptAttributes = attrs;
                }
 
                protected virtual bool CheckBase (TypeContainer container)
@@ -3886,6 +3880,11 @@ namespace Mono.CSharp {
                                if (InterfaceType == null)
                                        return false;
 
+                               if (InterfaceType.IsClass) {
+                                       Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
+                                       return false;
+                               }
+
                                // Compute the full name that we need to export.
                                Name = InterfaceType.FullName + "." + ShortName;
                                
@@ -4067,10 +4066,17 @@ namespace Mono.CSharp {
                                return false;
                        }
 
+                       try {
                        FieldBuilder = container.TypeBuilder.DefineField (
                                Name, t, Modifiers.FieldAttr (ModFlags));
 
                        TypeManager.RegisterFieldBase (FieldBuilder, this);
+                       }
+                       catch (ArgumentException) {
+                               Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
+                               return false;
+                       }
+
                        return true;
                }
 
index 3985e955ccc32f6174bcf7a121e70d7184bfc8fd..6e97979afc57dc2d023e9d05a1ec116a5f9be3d5 100755 (executable)
@@ -253,25 +253,12 @@ namespace Mono.CSharp {
                /// </summary>
                public bool HasReturnLabel;
 
-               /// <summary>
-               ///   Whether we are in a Finally block
-               /// </summary>
-               public bool InFinally;
-
-               /// <summary>
-               ///   Whether we are in a Try block
-               /// </summary>
-               public bool InTry;
-
                /// <summary>
                ///   Whether we are inside an iterator block.
                /// </summary>
                public bool InIterator;
 
-               /// <summary>
-               ///   Whether we need an explicit return statement at the end of the method.
-               /// </summary>
-               public bool NeedExplicitReturn;
+               public bool IsLastStatement;
                
                /// <summary>
                ///   Whether remapping of locals, parameters and fields is turned on.
@@ -279,11 +266,6 @@ namespace Mono.CSharp {
                /// </summary>
                public bool RemapToProxy;
 
-               /// <summary>
-               ///   Whether we are in a Catch block
-               /// </summary>
-               public bool InCatch;
-
                /// <summary>
                ///  Whether we are inside an unsafe block
                /// </summary>
@@ -433,7 +415,7 @@ namespace Mono.CSharp {
 
                public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
                {
-                       bool has_ret = false;
+                       bool unreachable = false;
 
                        if (!Location.IsNull (loc))
                                CurrentFile = loc.File;
@@ -464,10 +446,10 @@ namespace Mono.CSharp {
 
                                        block.Emit (this);
 
-                                       if ((reachability.Returns == FlowBranching.FlowReturns.Always) ||
-                                           (reachability.Throws == FlowBranching.FlowReturns.Always) ||
-                                           (reachability.Reachable == FlowBranching.FlowReturns.Never))
-                                               has_ret = true;
+                                       if (reachability.AlwaysReturns ||
+                                           reachability.AlwaysThrows ||
+                                           reachability.IsUnreachable)
+                                               unreachable = true;
                                        }
                            } catch (Exception e) {
                                        Console.WriteLine ("Exception caught by the compiler while compiling:");
@@ -477,7 +459,6 @@ namespace Mono.CSharp {
                                                Console.WriteLine ("                     Block being compiled: [{0},{1}]",
                                                                   CurrentBlock.StartLocation, CurrentBlock.EndLocation);
                                        }
-                                       
                                        Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
                                        Console.WriteLine (Report.FriendlyStackTrace (e));
                                        
@@ -485,12 +466,7 @@ namespace Mono.CSharp {
                            }
                        }
 
-                       if (ReturnType != null && !has_ret){
-                               //
-                               // FIXME: we need full flow analysis to implement this
-                               // correctly and emit an error instead of a warning.
-                               //
-                               //
+                       if (ReturnType != null && !unreachable){
                                if (!InIterator){
                                        Report.Error (161, loc, "Not all code paths return a value");
                                        return;
@@ -503,22 +479,22 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldloc, return_value);
                                ig.Emit (OpCodes.Ret);
                        } else {
-                               if (!InTry){
-                                       if (InIterator)
-                                               has_ret = true;
-                                       
-                                       if (!has_ret || HasReturnLabel) {
-                                               ig.Emit (OpCodes.Ret);
-                                               NeedExplicitReturn = false;
-                                       }
-                               }
-
-                               // Unfortunately, System.Reflection.Emit automatically emits a leave
-                               // to the end of a finally block.  This is a problem if no code is
-                               // following the try/finally block since we may jump to a point after
-                               // the end of the method. As a workaround, emit an explicit ret here.
+                               //
+                               // If `HasReturnLabel' is set, then we already emitted a
+                               // jump to the end of the method, so we must emit a `ret'
+                               // there.
+                               //
+                               // Unfortunately, System.Reflection.Emit automatically emits
+                               // a leave to the end of a finally block.  This is a problem
+                               // if no code is following the try/finally block since we may
+                               // jump to a point after the end of the method.
+                               // As a workaround, we're always creating a return label in
+                               // this case.
+                               //
 
-                               if (NeedExplicitReturn) {
+                               if ((block != null) && block.IsDestructor) {
+                                       // Nothing to do; S.R.E automatically emits a leave.
+                               } else if (HasReturnLabel || (!unreachable && !InIterator)) {
                                        if (ReturnType != null)
                                                ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
                                        ig.Emit (OpCodes.Ret);
@@ -606,22 +582,6 @@ namespace Mono.CSharp {
                /// </summary>
                public Label LoopBegin, LoopEnd;
 
-               /// <summary>
-               ///   Whether we are inside a loop and break/continue are possible.
-               /// </summary>
-               public bool  InLoop;
-
-               /// <summary>
-               ///   This is incremented each time we enter a try/catch block and
-               ///   decremented if we leave it.
-               /// </summary>
-               public int   TryCatchLevel;
-
-               /// <summary>
-               ///   The TryCatchLevel at the begin of the current loop.
-               /// </summary>
-               public int   LoopBeginTryCatchLevel;
-
                /// <summary>
                ///   Default target in a switch statement.   Only valid if
                ///   InSwitch is true
@@ -650,6 +610,14 @@ namespace Mono.CSharp {
                        return return_value;
                }
 
+               public void NeedReturnLabel ()
+               {
+                       if (!HasReturnLabel) {
+                               ReturnLabel = ig.DefineLabel ();
+                               HasReturnLabel = true;
+                       }
+               }
+
                //
                // Creates a field `name' with the type `t' on the proxy class
                //
index 47fc56ec5af35337755ce577ad962bda9e877bca..97f1e5a76d52796be57c4e98f557dc6da52a082c 100755 (executable)
@@ -192,6 +192,12 @@ namespace Mono.CSharp {
                        in_transit = true;
                        int errors = Report.Errors;
 
+                       //
+                       // We might have cleared Expr ourselves in a recursive definition
+                       //
+                       if (Expr == null)
+                               return null;
+                       
                        Expr = Expr.Resolve (const_ec);
 
                        in_transit = false;
index 4684a3a9326685ed71cb1b78977dbbad6b4faafd..6e9407ecc1257ef037d2a6d30f74f67754318f5a 100644 (file)
@@ -59,7 +59,7 @@ namespace Mono.CSharp {
                                if (TypeManager.IsValueType (expr_type))
                                        return new BoxedCast (expr);
                                if (expr is NullLiteral)
-                                       return new BoxedCast (expr);
+                                       return new NullCast (expr, target_type);
                        } else if (expr_type.IsSubclassOf (target_type)) {
                                //
                                // Special case: enumeration to System.Enum.
@@ -1036,6 +1036,18 @@ namespace Mono.CSharp {
                        Type expr_type = expr.Type;
                        Expression e;
 
+                       if (expr.eclass == ExprClass.MethodGroup){
+                               if (!TypeManager.IsDelegateType (target_type)){
+                                       Report.Error (428, loc,
+                                                     String.Format (
+                                                          "Cannot convert method group to `{0}', since it is not a delegate",
+                                                          TypeManager.CSharpName (target_type)));
+                                       return null;
+                               }
+
+                               return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+                       }
+
                        if (expr_type.Equals (target_type) && !(expr is NullLiteral))
                                return expr;
 
@@ -1502,6 +1514,13 @@ namespace Mono.CSharp {
                        if (source_type == TypeManager.object_type && !target_is_value_type)
                                return new ClassCast (source, target_type);
 
+                       //
+                       // Unboxing conversion.
+                       //
+                       if (((source_type == TypeManager.enum_type &&
+                               !(source is EmptyCast)) ||
+                               source_type == TypeManager.value_type) && target_is_value_type)
+                               return new UnboxCast (source, target_type);
 
                        //
                        // From any class S to any class-type T, provided S is a base class of T
index 82b1b91c7b98bc96df3ee32a718cddb8c74b8c8f..ee2f08d0f51bcf190c93b5385d191a8ae9909179 100755 (executable)
@@ -35,48 +35,55 @@ namespace Mono.CSharp
        
                IIteratorContainer iterator_container;
 
-               // <summary>
-               //   Current block is used to add statements as we find
-               //   them.  
-               // </summary>
+               /// <summary>
+               ///   Current block is used to add statements as we find
+               ///   them.  
+               /// </summary>
 
                Block      current_block;
 
-               // <summary>
-               //   Current interface is used by the various declaration
-               //   productions in the interface declaration to "add"
-               //   the interfaces as we find them.
-               // </summary>
+               /// <summary>
+                ///   If true, creates a toplevel block in the block production
+                ///   This is flagged by the delegate creation
+                /// </summary>
+                bool       create_toplevel_block;
+
+                /// <summary>
+               /// <summary>
+               ///   Current interface is used by the various declaration
+               ///   productions in the interface declaration to "add"
+               ///   the interfaces as we find them.
+               /// </summary>
                Interface  current_interface;
 
-               // <summary>
-               //   This is used by the unary_expression code to resolve
-               //   a name against a parameter.  
-               // </summary>
+               /// <summary>
+               ///   This is used by the unary_expression code to resolve
+               ///   a name against a parameter.  
+               /// </summary>
                Parameters current_local_parameters;
 
-               // <summary>
-               //   Using during property parsing to describe the implicit
-               //   value parameter that is passed to the "set" and "get"accesor
-               //   methods (properties and indexers).
-               // </summary>
+               /// <summary>
+               ///   Using during property parsing to describe the implicit
+               ///   value parameter that is passed to the "set" and "get"accesor
+               ///   methods (properties and indexers).
+               /// </summary>
                Expression implicit_value_parameter_type;
                Parameters indexer_parameters;
 
-               // <summary>
-               //   Used to determine if we are parsing the get/set pair
-               //   of an indexer or a property
-               // </summmary>
+               /// <summary>
+               ///   Used to determine if we are parsing the get/set pair
+               ///   of an indexer or a property
+               /// </summmary>
                bool  parsing_indexer;
 
-               //
-               // An out-of-band stack.
-               //
+               ///
+               /// An out-of-band stack.
+               ///
                Stack oob_stack;
 
-               //
-               // Switch stack.
-               //
+               ///
+               /// Switch stack.
+               ///
                Stack switch_stack;
 
                public bool yacc_verbose_flag;
@@ -84,9 +91,9 @@ namespace Mono.CSharp
                // Name of the file we are parsing
                public string name;
 
-               //
-               // The current file.
-               //
+               ///
+               /// The current file.
+               ///
                SourceFile file;
 %}
 
@@ -429,6 +436,13 @@ namespace_member_declaration
        | namespace_declaration {
                current_namespace.DeclarationFound = true;
          }
+
+       | field_declaration {
+               Report.Error (116, lexer.Location, "A namespace can only contain types and namespace declarations");
+         }
+       | method_declaration {
+               Report.Error (116, lexer.Location, "A namespace can only contain types and namespace declarations");
+         }
        ;
 
 type_declaration
@@ -460,22 +474,24 @@ attribute_sections
           {
                AttributeSection sect = (AttributeSection) $1;
 
-               if (sect.Target == "assembly") 
+               if (sect.Target == "assembly") {
                        RootContext.AddGlobalAttributeSection (current_container, sect);
-               
-
-               $$ = new Attributes ((AttributeSection) $1);
+                       $$ = null;
+               }
+               else
+                       $$ = new Attributes (sect);
           }
        | attribute_sections attribute_section
          {
-               Attributes attrs = null;
+               Attributes attrs = $1 as Attributes;
                AttributeSection sect = (AttributeSection) $2;
 
-               if (sect.Target == "assembly")
+               if (sect.Target == "assembly") {
                        RootContext.AddGlobalAttributeSection (current_container, sect);
-
-               if ($1 != null) {
-                       attrs = (Attributes) $1;
+               } else {
+                       if (attrs == null)
+                               attrs = new Attributes (sect);
+                       else
                        attrs.AddAttributeSection (sect);
                }
                
@@ -929,7 +945,8 @@ method_header
                GenericMethod generic = null;
                if ($5 != null) {
                        generic = new GenericMethod (current_namespace, current_container,
-                                                    (string) $4, lexer.Location);
+                                                    (string) $4, (Attributes) $1,
+                                                    lexer.Location);
 
                        CheckDef (generic.SetParameterInfo ((ArrayList) $5, (ArrayList) $10), generic.Name, generic.Location);
                        method = new Method (generic, (Expression) $3, (int) $2, (string) $4,
@@ -962,7 +979,8 @@ method_header
                GenericMethod generic = null;
                if ($5 != null) {
                        generic = new GenericMethod (current_namespace, current_container,
-                                                    (string) $4, lexer.Location);
+                                                    (string) $4, (Attributes) $1,
+                                                    lexer.Location);
 
                        CheckDef (generic.SetParameterInfo ((ArrayList) $5, (ArrayList) $10), generic.Name, generic.Location);
 
@@ -976,6 +994,21 @@ method_header
 
                current_local_parameters = (Parameters) $7;
 
+               $$ = method;
+         }
+       | opt_attributes
+         opt_modifiers
+         type 
+         modifiers member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         {
+               Report.Error (1585, lexer.Location, 
+                       String.Format ("Modifier {0} should appear before type", 
+                               Modifiers.Name ((int) $4)));
+               Method method = new Method (current_container, TypeManager.system_void_expr, 0,
+                                           (string) $5, (Parameters) $7, (Attributes) $1,
+                                           lexer.Location);
+
+               current_local_parameters = (Parameters) $7;
                $$ = method;
          }
        ;
@@ -1291,10 +1324,11 @@ interface_member_declaration
           }
        | interface_event_declaration 
           { 
+               if ($1 != null){
                InterfaceEvent e = (InterfaceEvent) $1;
-
                CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
          }
+         }
        | interface_indexer_declaration
          { 
                InterfaceIndexer i = (InterfaceIndexer) $1;
@@ -1374,6 +1408,14 @@ interface_event_declaration
                CheckIdentifierToken (yyToken);
                $$ = null;
          }
+       | opt_attributes opt_new EVENT type IDENTIFIER ASSIGN  {
+               Report.Error (68, lexer.Location, "Event declarations on interfaces can not be initialized.");
+               $$ = null;
+         }
+       | opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE event_accessor_declarations CLOSE_BRACE {
+               Report.Error (69, lexer.Location, "Event accessors not valid on interfaces");
+               $$ = null;
+         }
        ;
 
 interface_indexer_declaration 
@@ -1637,7 +1679,7 @@ destructor_declaration
                                 }
                         }
                         
-                       Method d = new Method (
+                       Method d = new Destructor (
                                current_container, TypeManager.system_void_expr, m, "Finalize", 
                                new Parameters (null, null, l), (Attributes) $1, l);
                  
@@ -1679,6 +1721,10 @@ event_declaration
          {
                Location loc = (Location) oob_stack.Pop ();
 
+               if ($8 == null){
+                       Report.Error (65, lexer.Location, "Event must have both add and remove accesors");
+                       $$ = null;
+               } else {
                Pair pair = (Pair) $8;
                Accessor add_accessor = null;
                Accessor rem_accessor = null;
@@ -1694,6 +1740,7 @@ event_declaration
                CheckDef (current_container.AddEvent (e), e.Name, loc);
                implicit_value_parameter_type = null;
          }
+         }
        ;
 
 event_accessor_declarations
@@ -1705,6 +1752,8 @@ event_accessor_declarations
        {
                $$ = new Pair ($2, $1);
        }       
+       | add_accessor_declaration  { $$ = null; } 
+       | remove_accessor_declaration { $$ = null; } 
        ;
 
 add_accessor_declaration
@@ -1991,6 +2040,13 @@ type_arguments
          }
        ;
        
+type_name_expression
+       : IDENTIFIER { $$ = new SimpleName ((string) $1, lexer.Location);}
+       | type_name_expression DOT IDENTIFIER { 
+               $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
+         }
+       ;
+
 /* 
  * Before you think of adding a return_type, notice that we have been
  * using two rules in the places where it matters (one rule using type
@@ -2524,7 +2580,9 @@ anonymous_method_expression
        : DELEGATE opt_anonymous_method_signature {
                oob_stack.Push (current_local_parameters);
                current_local_parameters = (Parameters)$2;
+               create_toplevel_block = true;
          } block {
+               create_toplevel_block = false;
                if (!RootContext.V2){
                        Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
                        $$ = null;
@@ -2945,8 +3003,13 @@ class_declaration
 
                if ($6 != null)
                        CheckDef (new_class.SetParameterInfo ((ArrayList) $6, (ArrayList) $8), new_class.Name, new_class.Location);
-               if ($7 != null)
+               if ($7 != null) {
+                       if (new_class.Name == "System.Object") {
+                               Report.Error (537, new_class.Location, "The class System.Object cannot have a base class or implement an interface.");
+                       }
+
                        new_class.Bases = (ArrayList) $7;
+               }
                current_container = current_container.Parent;
                CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
 
@@ -3104,8 +3167,12 @@ type_parameter_constraint
 block
        : OPEN_BRACE 
          {
+               if (current_block == null || create_toplevel_block){
+                       current_block = new ToplevelBlock (current_local_parameters, lexer.Location);
+               } else {
                current_block = new Block (current_block, current_local_parameters,
                                           lexer.Location, Location.Null);
+               }
          } 
          opt_statement_list CLOSE_BRACE 
          { 
index bf4bb4478e8ed556d0cc61365bcf3b9909ad2cd1..88f89e30398cb323e520589b98e43d26bc27c052 100755 (executable)
@@ -178,6 +178,8 @@ namespace Mono.CSharp
                const int max_id_size = 512;\r
                static char [] id_builder = new char [max_id_size];\r
 \r
+               static CharArrayHashtable [] identifiers = new CharArrayHashtable [max_id_size + 1];\r
+\r
                const int max_number_size = 128;\r
                static char [] number_builder = new char [max_number_size];\r
                static int number_pos;\r
@@ -383,6 +385,10 @@ namespace Mono.CSharp
                        Mono.CSharp.Location.Push (file);\r
                }\r
 \r
+               public static void Cleanup () {\r
+                       identifiers = null;\r
+               }\r
+\r
                bool is_identifier_start_character (char c)\r
                {\r
                        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || Char.IsLetter (c);\r
@@ -1181,6 +1187,19 @@ namespace Mono.CSharp
                        case Token.TYPEOF:\r
                        case Token.UNCHECKED:\r
                        case Token.UNSAFE:\r
+\r
+                               //\r
+                               // These can be part of a member access\r
+                               //\r
+                       case Token.INT:\r
+                       case Token.UINT:\r
+                       case Token.SHORT:\r
+                       case Token.USHORT:\r
+                       case Token.LONG:\r
+                       case Token.ULONG:\r
+                       case Token.DOUBLE:\r
+                       case Token.FLOAT:\r
+                       case Token.CHAR:\r
                                return true;\r
 \r
                        default:\r
@@ -1772,8 +1791,27 @@ namespace Mono.CSharp
                                return keyword;\r
                        }\r
 \r
+                       //\r
+                       // Keep identifiers in an array of hashtables to avoid needless\r
+                       // allocations\r
+                       //\r
+\r
+                       if (identifiers [pos] != null) {\r
+                               val = identifiers [pos][id_builder];\r
+                               if (val != null) {\r
+                                       return Token.IDENTIFIER;\r
+                               }\r
+                       }\r
+                       else\r
+                               identifiers [pos] = new CharArrayHashtable (pos);\r
+\r
                        val = new String (id_builder, 0, pos);\r
 \r
+                       char [] chars = new char [pos];\r
+                       Array.Copy (id_builder, chars, pos);\r
+\r
+                       identifiers [pos] [chars] = val;\r
+\r
                        return Token.IDENTIFIER;\r
                }\r
                \r
@@ -1985,7 +2023,6 @@ namespace Mono.CSharp
                        }\r
                                \r
                }\r
-\r
        }\r
 }\r
 \r
index 7f9ca703f1ec462d06ecd27c455aa97cdfc86862..e14ba889b6668a2884326788a31e3f2eac26299a 100755 (executable)
@@ -37,14 +37,30 @@ namespace Mono.CSharp {
                /// </summary>
                public readonly Location Location;
 
-               public MemberCore (string name, Location loc)
+               /// <summary>
+               ///   Attributes for this type
+               /// </summary>
+               Attributes attributes;
+
+               public MemberCore (string name, Attributes attrs, Location loc)
                {
                        Name = name;
                        Location = loc;
+                       attributes = attrs;
                }
 
                public abstract bool Define (TypeContainer parent);
 
+               public Attributes OptAttributes 
+               {
+                       get {
+                               return attributes;
+                       }
+                       set {
+                               attributes = value;
+                       }
+               }
+
                // 
                // Whehter is it ok to use an unsafe pointer in this type container
                //
@@ -106,8 +122,8 @@ namespace Mono.CSharp {
 
                TypeContainer parent;
 
-               public DeclSpace (NamespaceEntry ns, TypeContainer parent, string name, Location l)
-                       : base (name, l)
+               public DeclSpace (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
+                       : base (name, attrs, l)
                {
                        NamespaceEntry = ns;
                        Basename = name.Substring (1 + name.LastIndexOf ('.'));
index 68cb107d8218fcbe7fe445aa75b740f50cfc2829..024d5da673aab0ddf9a412190ed7a27f1c403890 100644 (file)
@@ -25,7 +25,6 @@ namespace Mono.CSharp {
        public class Delegate : DeclSpace {\r
                public Expression ReturnType;\r
                public Parameters      Parameters;\r
-               public Attributes      OptAttributes;\r
 \r
                public ConstructorBuilder ConstructorBuilder;\r
                public MethodBuilder      InvokeBuilder;\r
@@ -49,15 +48,14 @@ namespace Mono.CSharp {
                public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type,\r
                                 int mod_flags, string name, Parameters param_list,\r
                                 Attributes attrs, Location l)\r
-                       : base (ns, parent, name, l)\r
+                       : base (ns, parent, name, attrs, l)
+
                {\r
                        this.ReturnType = type;\r
                        ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,\r
                                                           IsTopLevel ? Modifiers.INTERNAL :\r
                                                           Modifiers.PRIVATE, l);\r
-                       Parameters      = param_list;\r
-                       OptAttributes   = attrs;\r
-               }\r
+                       Parameters      = param_list;\r          }\r
 \r
                public override TypeBuilder DefineType ()\r
                {\r
@@ -572,57 +570,64 @@ namespace Mono.CSharp {
                \r
        }\r
 \r
-       public class NewDelegate : Expression {\r
-\r
-               public ArrayList Arguments;\r
+       //\r
+       // Base class for `NewDelegate' and `ImplicitDelegateCreation'\r
+       //\r
+       public abstract class DelegateCreation : Expression {\r
+               protected MethodBase constructor_method;\r
+               protected MethodBase delegate_method;\r
+               protected Expression delegate_instance_expr;\r
 \r
-               MethodBase constructor_method;\r
-               MethodBase delegate_method;\r
-               Expression delegate_instance_expr;\r
+               public DelegateCreation () {}\r
 \r
-               public NewDelegate (Type type, ArrayList Arguments, Location loc)\r
+               public static void Error_NoMatchingMethodForDelegate (MethodGroupExpr mg, Type t, MethodBase method, Location loc)\r
                {\r
-                       this.type = type;\r
-                       this.Arguments = Arguments;\r
-                       this.loc  = loc; \r
+                       string method_desc;\r
+\r
+                       if (mg.Methods.Length > 1)\r
+                               method_desc = mg.Methods [0].Name;\r
+                       else\r
+                               method_desc = Invocation.FullMethodDesc (mg.Methods [0]);\r
+\r
+                       ParameterData param = Invocation.GetParameterData (method);\r
+                       string delegate_desc = Delegate.FullDelegateDesc (t, method, param);\r
+\r
+                       Report.Error (123, loc, "Method '" + method_desc + "' does not " +\r
+                                     "match delegate '" + delegate_desc + "'");\r
                }\r
 \r
-               public override Expression DoResolve (EmitContext ec)\r
+               public override void Emit (EmitContext ec)\r
                {\r
-                       if (Arguments == null || Arguments.Count != 1) {\r
-                               Report.Error (149, loc,\r
-                                             "Method name expected");\r
-                               return null;\r
-                       }\r
+                       if (delegate_instance_expr == null ||\r
+                           delegate_method.IsStatic)\r
+                               ec.ig.Emit (OpCodes.Ldnull);\r
+                       else\r
+                               delegate_instance_expr.Emit (ec);\r
+                       \r
+                       if (delegate_method.IsVirtual) {\r
+                               ec.ig.Emit (OpCodes.Dup);\r
+                               ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);\r
+                       } else\r
+                               ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);\r
+               }\r
 \r
+               protected bool ResolveConstructorMethod (EmitContext ec)\r
+               {\r
                        Expression ml = Expression.MemberLookup (\r
                                ec, type, ".ctor", loc);\r
 \r
                        if (!(ml is MethodGroupExpr)) {\r
                                Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");\r
-                               return null;\r
+                               return false;\r
                        }\r
 \r
                        constructor_method = ((MethodGroupExpr) ml).Methods [0];\r
-                       Argument a = (Argument) Arguments [0];\r
-                       \r
-                       if (!a.ResolveMethodGroup (ec, Location))\r
-                               return null;\r
-                       \r
-                       Expression e = a.Expr;\r
-\r
-                       Expression invoke_method = Expression.MemberLookup (\r
-                               ec, type, "Invoke", MemberTypes.Method,\r
-                               Expression.AllBindingFlags, loc);\r
-\r
-                       if (invoke_method == null) {\r
-                               Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");\r
-                               return null;\r
-                       }\r
-\r
-                       if (e is MethodGroupExpr) {\r
-                               MethodGroupExpr mg = (MethodGroupExpr) e;\r
+                       return true;\r
+               }\r
 \r
+               protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)\r
+               {\r
                                foreach (MethodInfo mi in mg.Methods){\r
                                        delegate_method  = Delegate.VerifyMethod (ec, type, mi, loc);\r
 \r
@@ -631,19 +636,7 @@ namespace Mono.CSharp {
                                }\r
                                        \r
                                if (delegate_method == null) {\r
-                                       string method_desc;\r
-                                       if (mg.Methods.Length > 1)\r
-                                               method_desc = mg.Methods [0].Name;\r
-                                       else\r
-                                               method_desc = Invocation.FullMethodDesc (mg.Methods [0]);\r
-\r
-                                       MethodBase dm = ((MethodGroupExpr) invoke_method).Methods [0];\r
-                                       ParameterData param = Invocation.GetParameterData (dm);\r
-                                       string delegate_desc = Delegate.FullDelegateDesc (type, dm, param);\r
-\r
-                                       Report.Error (123, loc, "Method '" + method_desc + "' does not " +\r
-                                                     "match delegate '" + delegate_desc + "'");\r
-\r
+                               Error_NoMatchingMethodForDelegate (mg, type, delegate_method, loc);\r
                                        return null;\r
                                }\r
 \r
@@ -684,6 +677,80 @@ namespace Mono.CSharp {
                                eclass = ExprClass.Value;\r
                                return this;\r
                        }\r
+       }\r
+\r
+       //\r
+       // Created from the conversion code\r
+       //\r
+       public class ImplicitDelegateCreation : DelegateCreation {\r
+\r
+               ImplicitDelegateCreation (Type t, Location l)\r
+               {\r
+                       type = t;\r
+                       loc = l;\r
+               }\r
+\r
+               public override Expression DoResolve (EmitContext ec)\r
+               {\r
+                       return this;\r
+               }\r
+               \r
+               static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc)\r
+               {\r
+                       ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);\r
+                       if (d.ResolveConstructorMethod (ec))\r
+                               return d.ResolveMethodGroupExpr (ec, mge);\r
+                       else\r
+                               return null;\r
+               }\r
+       }\r
+       \r
+       //\r
+       // A delegate-creation-expression, invoked from the `New' class \r
+       //\r
+       public class NewDelegate : DelegateCreation {\r
+               public ArrayList Arguments;\r
+\r
+               //\r
+               // This constructor is invoked from the `New' expression\r
+               //\r
+               public NewDelegate (Type type, ArrayList Arguments, Location loc)\r
+               {\r
+                       this.type = type;\r
+                       this.Arguments = Arguments;\r
+                       this.loc  = loc; \r
+               }\r
+\r
+               public override Expression DoResolve (EmitContext ec)\r
+               {\r
+                       if (Arguments == null || Arguments.Count != 1) {\r
+                               Report.Error (149, loc,\r
+                                             "Method name expected");\r
+                               return null;\r
+                       }\r
+\r
+                       if (!ResolveConstructorMethod (ec))\r
+                               return null;\r
+\r
+                       Argument a = (Argument) Arguments [0];\r
+                       \r
+                       Expression invoke_method = Expression.MemberLookup (\r
+                               ec, type, "Invoke", MemberTypes.Method,\r
+                               Expression.AllBindingFlags, loc);\r
+\r
+                       if (invoke_method == null) {\r
+                               Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");\r
+                               return null;\r
+                       }\r
+\r
+                       if (!a.ResolveMethodGroup (ec, loc))\r
+                               return null;\r
+                       \r
+                       Expression e = a.Expr;\r
+\r
+                       MethodGroupExpr mg = e as MethodGroupExpr;\r
+                       if (mg != null)\r
+                               return ResolveMethodGroupExpr (ec, mg);\r
 \r
                        Type e_type = e.Type;\r
 \r
@@ -710,8 +777,7 @@ namespace Mono.CSharp {
                \r
                public override void Emit (EmitContext ec)\r
                {\r
-                       if (delegate_instance_expr == null ||\r
-                           delegate_method.IsStatic)\r
+                       if (delegate_instance_expr == null || delegate_method.IsStatic)\r
                                ec.ig.Emit (OpCodes.Ldnull);\r
                        else\r
                                delegate_instance_expr.Emit (ec);\r
index 1e53f92ee8ccd5e5c54ab7022908ac7cd2013e67..120c295f41d72d56619eb02154934b17b627d895 100755 (executable)
@@ -76,6 +76,8 @@ namespace Mono.CSharp
                //
                static ArrayList resources;
                static ArrayList embedded_resources;
+               static string win32ResourceFile;
+               static string win32IconFile;
                
                //
                // An array of the defines from the command line
@@ -220,6 +222,8 @@ namespace Mono.CSharp
                                "Resources:\n" +
                                "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
                                "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
+                               "   -win32res:FILE          Specifies Win32 resource file (.res)\n" +
+                               "   -win32icon:FILE         Use this icon for the output\n" +
                                "   --mcs-debug X      Sets MCS debugging level to X\n" +
                                 "   @file              Read response file for more options\n\n" +
                                "Options can be of the form -option or /option");
@@ -1017,6 +1021,24 @@ namespace Mono.CSharp
                                }
                                return true;
                        }
+                       case "/win32res": {
+                               if (value == "") {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               win32ResourceFile = value;
+                               return true;
+                       }
+                       case "/win32icon": {
+                               if (value == "") {
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               win32IconFile = value;
+                               return true;
+                       }
                        case "/doc": {
                                if (value == ""){
                                        Report.Error (5, arg + " requires an argument");
@@ -1136,10 +1158,6 @@ namespace Mono.CSharp
                        case "/fullpaths":
                                return true;
 
-                       case "/win32icon":
-                               Report.Error (5, "/win32icon is currently not supported");
-                               return true;
-                               
                        case "/v2":
                        case "/2":
                                SetupV2 ();
@@ -1279,17 +1297,33 @@ namespace Mono.CSharp
                        if (tokenize)
                                return true;
                        
+                       //
+                       // If we are an exe, require a source file for the entry point
+                       //
+                       if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){
                        if (first_source == null){
                                Report.Error (2008, "No files to compile were specified");
                                return false;
                        }
 
+                       }
+
+                       //
+                       // If there is nothing to put in the assembly, and we are not a library
+                       //
+                       if (first_source == null && embedded_resources == null && resources == null){
+                                       Report.Error (2008, "No files to compile were specified");
+                                       return false;
+                       }
+
                        if (Report.Errors > 0)
                                return false;
                        
                        if (parse_only)
                                return true;
                        
+                       Tokenizer.Cleanup ();
+                       
                        //
                        // Load Core Library for default compilation
                        //
@@ -1493,6 +1527,29 @@ namespace Mono.CSharp
                                }
                        }
 
+                       //
+                       // Add Win32 resources
+                       //
+
+                       CodeGen.AssemblyBuilder.DefineVersionInfoResource ();
+
+                       if (win32ResourceFile != null) {
+                               try {
+                                       CodeGen.AssemblyBuilder.DefineUnmanagedResource (win32ResourceFile);
+                               }
+                               catch (ArgumentException) {
+                                       Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead.");
+                               }
+                       }
+
+                       if (win32IconFile != null) {
+                               MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+                               if (define_icon == null) {
+                                       Report.Warning (0, new Location (-1), "Cannot embed icon resource on this runtime: try the Mono runtime instead.");
+                               }
+                               define_icon.Invoke (CodeGen.AssemblyBuilder, new object [] { win32IconFile });
+                       }
+
                        if (Report.Errors > 0)
                                return false;
                        
index 6a510740d2cbda16be24f34419ce8a94d64876f3..26b6c6f376eb0fe56329e910566f344af4de69d2 100755 (executable)
@@ -314,10 +314,12 @@ namespace Mono.CSharp {
                                break;
 
                        case ExprClass.MethodGroup:
+                               if (!RootContext.V2){
                                if ((flags & ResolveFlags.MethodGroup) == 0) {
                                        ((MethodGroupExpr) e).ReportUsageError ();
                                        return null;
                                }
+                               }
                                break;
 
                        case ExprClass.Value:
@@ -405,6 +407,12 @@ namespace Mono.CSharp {
                /// </remarks>
                public abstract void Emit (EmitContext ec);
 
+               public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       Emit (ec);
+                       ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+               }
+
                /// <summary>
                ///   Protected constructor.  Only derivate types should
                ///   be able to be created
@@ -663,11 +671,15 @@ namespace Mono.CSharp {
                                Report.Error (
                                        122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." +
                                        name + "' is inaccessible due to its protection level");
-                       else
+                       else if (name == ".ctor") {
+                               Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
+                                                                      TypeManager.CSharpName (queried_type)));
+                       } else {
                                Report.Error (
                                        122, loc, "`" + name + "' is inaccessible due to its " +
                                        "protection level");
                }
+               }
 
                static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
                {
@@ -1314,6 +1326,12 @@ namespace Mono.CSharp {
        public class EmptyCast : Expression {
                protected Expression child;
                
+               public Expression Child {
+                       get {
+                               return child;
+                       }
+               }               
+
                public EmptyCast (Expression child, Type return_type)
                {
                        eclass = child.eclass;
@@ -1958,19 +1976,19 @@ namespace Mono.CSharp {
                                alias_value = null;
 
                        if (ec.ResolvingTypeTree){
-                               if (alias_value != null){
-                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
-                                               return new TypeExpression (t, loc);
-                               }
-
                                int errors = Report.Errors;
-                               Type dt = ec.DeclSpace.FindType (loc, Name);
+                               Type dt = ds.FindType (loc, Name);
                                
                                if (Report.Errors != errors)
                                        return null;
                                
                                if (dt != null)
                                        return new TypeExpression (dt, loc);
+
+                               if (alias_value != null){
+                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
+                                               return new TypeExpression (t, loc);
+                               }
                        }
 
                        //
@@ -2749,9 +2767,21 @@ namespace Mono.CSharp {
                        // Handle initonly fields specially: make a copy and then
                        // get the address of the copy.
                        //
-                       if (FieldInfo.IsInitOnly && !ec.IsConstructor){
+                       bool need_copy;
+                       if (FieldInfo.IsInitOnly){
+                               need_copy = true;
+                               if (ec.IsConstructor){
+                                       if (FieldInfo.IsStatic){
+                                               if (ec.IsStatic)
+                                                       need_copy = false;
+                                       } else
+                                               need_copy = false;
+                               }
+                       } else
+                               need_copy = false;
+                       
+                       if (need_copy){
                                LocalBuilder local;
-                               
                                Emit (ec);
                                local = ig.DeclareLocal (type);
                                ig.Emit (OpCodes.Stloc, local);
@@ -2759,9 +2789,10 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (FieldInfo.IsStatic)
+
+                       if (FieldInfo.IsStatic){
                                ig.Emit (OpCodes.Ldsflda, FieldInfo);
-                       else {
+                       else {
                                //
                                // In the case of `This', we call the AddressOf method, which will
                                // only load the pointer, and not perform an Ldobj immediately after
index 06f4c9e0cf7e8e0263c831b685f425995711340a..e8e7dd3cb768f13f5e33c1da53802c918e65df65 100755 (executable)
@@ -23,7 +23,6 @@ namespace Mono.CSharp {
                ArrayList ordered_enums;
                
                public Expression BaseType;
-               public Attributes  OptAttributes;
                
                public Type UnderlyingType;
 
@@ -51,12 +50,11 @@ namespace Mono.CSharp {
 
                public Enum (NamespaceEntry ns, TypeContainer parent, Expression type, int mod_flags,
                             string name, Attributes attrs, Location l)
-                       : base (ns, parent, name, l)
+                       : base (ns, parent, name, attrs, l)
                {
                        this.BaseType = type;
                        ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
                                                    IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE, l);
-                       OptAttributes = attrs;
 
                        ordered_enums = new ArrayList ();
                        member_to_location = new Hashtable ();
index 45866fd0654d2c97898ca51d0dd293630db3f70a..e5da8c12017952a69bb21fedaaf6b10221930617 100755 (executable)
@@ -605,16 +605,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   This will emit the child expression for `ec' avoiding the logical
-               ///   not.  The parent will take care of changing brfalse/brtrue
-               /// </summary>
-               public void EmitLogicalNot (EmitContext ec)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (Oper != Operator.LogicalNot)
-                               throw new Exception ("EmitLogicalNot can only be called with !expr");
-
-                       Expr.Emit (ec);
+                       if (Oper == Operator.LogicalNot)
+                               Expr.EmitBranchable (ec, target, !onTrue);
+                       else
+                               base.EmitBranchable (ec, target, onTrue);
                }
 
                public override string ToString ()
@@ -651,14 +647,14 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
 
                        if (temporary != null){
-                               if (have_temporary){
+                               if (have_temporary) {
                                        temporary.Emit (ec);
-                                       return;
-                               }
+                               } else {
                                expr.Emit (ec);
                                ec.ig.Emit (OpCodes.Dup);
                                temporary.Store (ec);
                                have_temporary = true;
+                               }
                        } else
                                expr.Emit (ec);
                        
@@ -1050,6 +1046,8 @@ namespace Mono.CSharp {
                                ia.EmitAssign (ec, temp_storage);
                                break;
                        }
+
+                       temp_storage.Release (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -1152,6 +1150,35 @@ namespace Mono.CSharp {
                        throw new Exception ("never reached");
                }
 
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       switch (action){
+                       case Action.AlwaysFalse:
+                               if (! onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.AlwaysTrue:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.LeaveOnStack:
+                               // the `e != null' rule.
+                               expr.Emit (ec);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       case Action.Probe:
+                               expr.Emit (ec);
+                               ig.Emit (OpCodes.Isinst, probe_type);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       }
+                       throw new Exception ("never reached");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        Expression e = base.DoResolve (ec);
@@ -2283,10 +2310,6 @@ namespace Mono.CSharp {
                                }
                        }
                        
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
                        //
                        // Step 0: String concatenation (because overloading will get this wrong)
                        //
@@ -2463,8 +2486,16 @@ namespace Mono.CSharp {
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
-                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
-                                   r.IsSubclassOf (TypeManager.delegate_type)) {
+                               if (l.IsSubclassOf (TypeManager.delegate_type)){
+                                       if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
+                                               Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+                                               if (tmp == null)
+                                                       return null;
+                                               right = tmp;
+                                               r = right.Type;
+                                       }
+                               
+                                       if (r.IsSubclassOf (TypeManager.delegate_type)){
                                        MethodInfo method;
                                        ArrayList args = new ArrayList (2);
                                        
@@ -2484,6 +2515,7 @@ namespace Mono.CSharp {
 
                                        return new BinaryDelegate (l, method, args);
                                }
+                               }
 
                                //
                                // Pointer arithmetic:
@@ -2528,7 +2560,8 @@ namespace Mono.CSharp {
                                Expression temp;
 
                                // U operator - (E e, E f)
-                               if (lie && rie && oper == Operator.Subtraction){
+                               if (lie && rie){
+                                       if (oper == Operator.Subtraction){
                                        if (l == r){
                                                type = TypeManager.EnumToUnderlying (l);
                                                return this;
@@ -2536,6 +2569,7 @@ namespace Mono.CSharp {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
                                }
+                               }
                                        
                                //
                                // operator + (E e, U x)
@@ -2545,9 +2579,18 @@ namespace Mono.CSharp {
                                        Type enum_type = lie ? l : r;
                                        Type other_type = lie ? r : l;
                                        Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
-;
                                        
                                        if (underlying_type != other_type){
+                                               temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
+                                               if (temp != null){
+                                                       if (lie)
+                                                               right = temp;
+                                                       else
+                                                               left = temp;
+                                                       type = enum_type;
+                                                       return this;
+                                               }
+                                                       
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
@@ -2737,7 +2780,7 @@ namespace Mono.CSharp {
                ///   The expression's code is generated, and we will generate a branch to `target'
                ///   if the resulting expression value is equal to isTrue
                /// </remarks>
-               public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
                        ILGenerator ig = ec.ig;
 
@@ -2747,130 +2790,79 @@ namespace Mono.CSharp {
                        // but on top of that we want for == and != to use a special path
                        // if we are comparing against null
                        //
-                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                       if (oper == Operator.Equality || oper == Operator.Inequality) {
                                bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
 
-                               if (left is NullLiteral){
+                               if (left is NullLiteral || left is IntConstant && ((IntConstant) left).Value == 0) {
                                        right.Emit (ec);
                                        if (my_on_true)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (right is NullLiteral){
+                                       
+                                       return;
+                               } else if (right is NullLiteral || right is IntConstant && ((IntConstant) right).Value == 0){
                                        left.Emit (ec);
                                        if (my_on_true)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
+                                       
+                                       return;
                                } else if (left is BoolConstant){
                                        right.Emit (ec);
                                        if (my_on_true != ((BoolConstant) left).Value)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
+                                       
+                                       return;
                                } else if (right is BoolConstant){
                                        left.Emit (ec);
                                        if (my_on_true != ((BoolConstant) right).Value)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
+                                       
+                                       return;
                                }
 
-                       } else if (oper == Operator.LogicalAnd){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
+                       } else if (oper == Operator.LogicalAnd) {
 
-                                       if (onTrue){
+                               if (onTrue) {
                                                Label tests_end = ig.DefineLabel ();
                                                
-                                               if (left_binary.EmitBranchable (ec, tests_end, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, true)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
+                                       left.EmitBranchable (ec, tests_end, false);
+                                       right.EmitBranchable (ec, target, true);
                                                        ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
                                        } else {
-                                               if (left_binary.EmitBranchable (ec, target, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-                                                               
-                                                               if (right_binary.EmitBranchable (ec, target, false))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       if (onTrue)
-                                                               ig.Emit (OpCodes.Brtrue, target);
-                                                       else
-                                                               ig.Emit (OpCodes.Brfalse, target);
-                                                       return true;
-                                               }
+                                       left.EmitBranchable (ec, target, false);
+                                       right.EmitBranchable (ec, target, false);
                                        }
-                                       //
-                                       // Give up, and let the regular Emit work, but we could
-                                       // also optimize the left-non-Branchable, but-right-Branchable
-                                       //
-                               }
-                               return false;
-                       } else if (oper == Operator.LogicalOr){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
 
-                                       if (onTrue){
-                                               if (left_binary.EmitBranchable (ec, target, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
+                               return;
                                                                
-                                                               if (right_binary.EmitBranchable (ec, target, true))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
-                                                       return true;
-                                               }
+                       } else if (oper == Operator.LogicalOr){
+                               if (onTrue) {
+                                       left.EmitBranchable (ec, target, true);
+                                       right.EmitBranchable (ec, target, true);
                                                
-                                               //
-                                               // Give up, and let the regular Emit work, but we could
-                                               // also optimize the left-non-Branchable, but-right-Branchable
-                                               //
                                        } else {
                                                Label tests_end = ig.DefineLabel ();
+                                       left.EmitBranchable (ec, tests_end, true);
+                                       right.EmitBranchable (ec, target, false);
+                                       ig.MarkLabel (tests_end);
+                               }
                                                
-                                               if (left_binary.EmitBranchable (ec, tests_end, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
+                               return;
 
-                                                               if (right_binary.EmitBranchable (ec, target, false)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brfalse, target);
-                                                       ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
-                                       }
+                       } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
+                                    oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
+                                    oper == Operator.Equality        || oper == Operator.Inequality)) {
+                               base.EmitBranchable (ec, target, onTrue);
+                               return;
                                }
                                
-                               return false;
-                       } else if (!(oper == Operator.LessThan ||
-                               oper == Operator.GreaterThan ||
-                               oper == Operator.LessThanOrEqual ||
-                               oper == Operator.GreaterThanOrEqual))
-                               return false;
-                       
                        left.Emit (ec);
                        right.Emit (ec);
 
@@ -2949,12 +2941,10 @@ namespace Mono.CSharp {
                                        else
                                                ig.Emit (OpCodes.Blt, target);
                                break;
-
                        default:
-                               return false;
+                               Console.WriteLine (oper);
+                               throw new Exception ("what is THAT");
                        }
-                       
-                       return true;
                }
                
                public override void Emit (EmitContext ec)
@@ -2967,52 +2957,26 @@ namespace Mono.CSharp {
                        // Handle short-circuit operators differently
                        // than the rest
                        //
-                       if (oper == Operator.LogicalAnd){
+                       if (oper == Operator.LogicalAnd) {
                                Label load_zero = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
-
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
 
-                                       if (left_binary.EmitBranchable (ec, load_zero, false)){
+                               left.EmitBranchable (ec, load_zero, false);
                                                right.Emit (ec);
                                                ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       }
-                               }
 
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brfalse, load_zero);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
                                ig.MarkLabel (load_zero);
                                ig.Emit (OpCodes.Ldc_I4_0);
                                ig.MarkLabel (end);
                                return;
-                       } else if (oper == Operator.LogicalOr){
+                       } else if (oper == Operator.LogicalOr) {
                                Label load_one = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
                                
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (left_binary.EmitBranchable (ec, load_one, true)){
+                               left.EmitBranchable (ec, load_one, true);
                                                right.Emit (ec);
                                                ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       } 
-                               }
 
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brtrue, load_one);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
                                ig.MarkLabel (load_one);
                                ig.Emit (OpCodes.Ldc_I4_1);
                                ig.MarkLabel (end);
@@ -3306,7 +3270,7 @@ namespace Mono.CSharp {
 
                        ig.Emit (OpCodes.Nop);
 
-                       Statement.EmitBoolExpression (ec, is_and ? op_false : op_true, false_target, false);
+                       (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
                        left.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -3510,7 +3474,7 @@ namespace Mono.CSharp {
                        Label false_target = ig.DefineLabel ();
                        Label end_target = ig.DefineLabel ();
 
-                       Statement.EmitBoolExpression (ec, expr, false_target, false);
+                       expr.EmitBranchable (ec, false_target, false);
                        trueExpr.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -4155,6 +4119,14 @@ namespace Mono.CSharp {
                                        // we can optimize this case: a positive int32
                                        // always fits on a uint64
                                        //
+
+                                        //
+                                        // This special case is needed because csc behaves like this.
+                                        // int -> uint is better than int -> ulong!
+                                        //
+                                        if (q == TypeManager.uint32_type)
+                                                return 0;
+                                        
                                        if (q == TypeManager.int64_type)
                                                return 0;
                                        else if (value >= 0)
@@ -6208,10 +6180,7 @@ namespace Mono.CSharp {
                                                        ig.Emit (OpCodes.Ldelema, etype);
                                                }
 
-                                               ig.Emit (OpCodes.Nop);
                                                e.Emit (ec);
-                                               ig.Emit (OpCodes.Nop);
-                                               ig.Emit (OpCodes.Nop);
 
                                                 if (dims == 1)
                                                         ArrayAccess.EmitStoreOpcode (ig, array_element_type);
@@ -8201,7 +8170,8 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
-                       if (ec.InCatch || ec.InFinally){
+                       if (ec.CurrentBranching.InCatch () ||
+                           ec.CurrentBranching.InFinally (true)) {
                                Error (255,
                                              "stackalloc can not be used in a catch or finally block");
                                return null;
index 75eb9c2a19e2d0463d881d9675f23d92fcbf5c2c..fdcbf56c745b77b311688435a248051c943c57a9 100644 (file)
@@ -33,7 +33,7 @@ namespace Mono.CSharp
                        Conditional,
 
                        // A loop block.
-                       LoopBlock,
+                       Loop,
 
                        // Try/Catch block.
                        Exception,
@@ -115,6 +115,60 @@ namespace Mono.CSharp
                                return cloned;
                        }
 
+                       // <summary>
+                       //   Performs an `And' operation on the FlowReturns status
+                       //   (for instance, a block only returns Always if all its siblings
+                       //   always return).
+                       // </summary>
+                       public static FlowReturns AndFlowReturns (FlowReturns a, FlowReturns b)
+                       {
+                               if (a == FlowReturns.Undefined)
+                                       return b;
+
+                               switch (a) {
+                               case FlowReturns.Never:
+                                       if (b == FlowReturns.Never)
+                                               return FlowReturns.Never;
+                                       else
+                                               return FlowReturns.Sometimes;
+
+                               case FlowReturns.Sometimes:
+                                       return FlowReturns.Sometimes;
+
+                               case FlowReturns.Always:
+                                       if (b == FlowReturns.Always)
+                                               return FlowReturns.Always;
+                                       else
+                                               return FlowReturns.Sometimes;
+
+                               default:
+                                       throw new ArgumentException ();
+                               }
+                       }
+
+                       public static FlowReturns OrFlowReturns (FlowReturns a, FlowReturns b)
+                       {
+                               if (a == FlowReturns.Undefined)
+                                       return b;
+
+                               switch (a) {
+                               case FlowReturns.Never:
+                                       return b;
+
+                               case FlowReturns.Sometimes:
+                                       if (b == FlowReturns.Always)
+                                               return FlowReturns.Always;
+                                       else
+                                               return FlowReturns.Sometimes;
+
+                               case FlowReturns.Always:
+                                       return FlowReturns.Always;
+
+                               default:
+                                       throw new ArgumentException ();
+                               }
+                       }
+
                        public static void And (ref Reachability a, Reachability b, bool do_break)
                        {
                                if (a == null) {
@@ -180,6 +234,16 @@ namespace Mono.CSharp
                                a.reachable = AndFlowReturns (a.reachable, b.reachable);
                        }
 
+                       public void Or (Reachability b)
+                       {
+                               returns = OrFlowReturns (returns, b.returns);
+                               breaks = OrFlowReturns (breaks, b.breaks);
+                               throws = OrFlowReturns (throws, b.throws);
+                               barrier = OrFlowReturns (barrier, b.barrier);
+
+                               update ();
+                       }
+
                        public static Reachability Never ()
                        {
                                return new Reachability (
@@ -296,7 +360,7 @@ namespace Mono.CSharp
                {
                        switch (type) {
                        case BranchingType.Exception:
-                               return new FlowBranchingException (parent, type, block, loc);
+                               return new FlowBranchingException (parent, block, loc);
 
                        case BranchingType.Switch:
                                return new FlowBranchingBlock (parent, type, SiblingType.SwitchSection, block, loc);
@@ -346,37 +410,6 @@ namespace Mono.CSharp
                static int next_id = 0;
                int id;
 
-               // <summary>
-               //   Performs an `And' operation on the FlowReturns status
-               //   (for instance, a block only returns Always if all its siblings
-               //   always return).
-               // </summary>
-               public static FlowReturns AndFlowReturns (FlowReturns a, FlowReturns b)
-               {
-                       if (a == FlowReturns.Undefined)
-                               return b;
-
-                       switch (a) {
-                       case FlowReturns.Never:
-                               if (b == FlowReturns.Never)
-                                       return FlowReturns.Never;
-                               else
-                                       return FlowReturns.Sometimes;
-
-                       case FlowReturns.Sometimes:
-                               return FlowReturns.Sometimes;
-
-                       case FlowReturns.Always:
-                               if (b == FlowReturns.Always)
-                                       return FlowReturns.Always;
-                               else
-                                       return FlowReturns.Sometimes;
-
-                       default:
-                               throw new ArgumentException ();
-                       }
-               }
-
                // <summary>
                //   The vector contains a BitArray with information about which local variables
                //   and parameters are already initialized at the current code position.
@@ -441,13 +474,17 @@ namespace Mono.CSharp
                                this.CountLocals = num_locals;
 
                                if (parent != null) {
+                                       if (num_locals > 0)
                                        locals = new MyBitVector (parent.locals, CountLocals);
+                                       
                                        if (num_params > 0)
                                                parameters = new MyBitVector (parent.parameters, num_params);
 
                                        reachability = parent.Reachability.Clone ();
                                } else {
+                                       if (num_locals > 0)
                                        locals = new MyBitVector (null, CountLocals);
+                                       
                                        if (num_params > 0)
                                                parameters = new MyBitVector (null, num_params);
 
@@ -481,9 +518,12 @@ namespace Mono.CSharp
                        {
                                UsageVector retval = new UsageVector (Type, null, Location, CountParameters, CountLocals);
 
+                               if (retval.locals != null)
                                retval.locals = locals.Clone ();
+                               
                                if (parameters != null)
                                        retval.parameters = parameters.Clone ();
+                               
                                retval.reachability = reachability.Clone ();
 
                                return retval;
@@ -570,33 +610,33 @@ namespace Mono.CSharp
 
                                Report.Debug (2, "  MERGING CHILD", this, IsDirty,
                                              result.ParameterVector, result.LocalVector,
-                                             result.Reachability, Type);
+                                             result.Reachability, reachability, Type);
 
-                               reachability = result.Reachability;
+                               Reachability new_r = result.Reachability;
 
-                               if (branching.Type == BranchingType.LoopBlock) {
-                                       bool may_leave_loop = reachability.MayBreak;
-                                       reachability.ResetBreaks ();
+                               if (branching.Type == BranchingType.Loop) {
+                                       bool may_leave_loop = new_r.MayBreak;
+                                       new_r.ResetBreaks ();
 
                                        if (branching.Infinite && !may_leave_loop) {
-                                               if (reachability.Returns == FlowReturns.Sometimes) {
+                                               if (new_r.Returns == FlowReturns.Sometimes) {
                                                        // If we're an infinite loop and do not break,
                                                        // the code after the loop can never be reached.
                                                        // However, if we may return from the loop,
                                                        // then we do always return (or stay in the
                                                        // loop forever).
-                                                       reachability.SetReturns ();
+                                                       new_r.SetReturns ();
                        }
 
-                                               reachability.SetBarrier ();
+                                               new_r.SetBarrier ();
                                        } else {
-                                               if (reachability.Returns == FlowReturns.Always) {
+                                               if (new_r.Returns == FlowReturns.Always) {
                                                        // We're either finite or we may leave the loop.
-                                                       reachability.SetReturnsSometimes ();
+                                                       new_r.SetReturnsSometimes ();
                        }
                        }
                                } else if (branching.Type == BranchingType.Switch)
-                                       reachability.ResetBreaks ();
+                                       new_r.ResetBreaks ();
 
                                //
                                // We've now either reached the point after the branching or we will
@@ -607,20 +647,23 @@ namespace Mono.CSharp
                                // we need to look at (see above).
                                //
 
-                               if ((Type == SiblingType.SwitchSection) && !reachability.IsUnreachable) {
+                               if ((Type == SiblingType.SwitchSection) && !new_r.IsUnreachable) {
                                        Report.Error (163, Location,
                                                      "Control cannot fall through from one " +
                                                              "case label to another");
                                        return result;
                                        }
 
-                               if (result.LocalVector != null)
+                               if (locals != null && result.LocalVector != null)
                                        locals.Or (result.LocalVector);
 
                                if (result.ParameterVector != null)
                                        parameters.Or (result.ParameterVector);
 
-                               Report.Debug (2, "  MERGING CHILD DONE", this, result);
+                               reachability.Or (new_r);
+
+                               Report.Debug (2, "  MERGING CHILD DONE", this, result,
+                                             new_r, reachability);
 
                                IsDirty = true;
 
@@ -647,7 +690,7 @@ namespace Mono.CSharp
                                                MergeFinally (branching, f_origins, parameters);
                                }
 
-                               if (f_vector != null)
+                               if (f_vector != null && f_vector.LocalVector != null)
                                        MyBitVector.Or (ref locals, f_vector.LocalVector);
                        }
 
@@ -686,11 +729,14 @@ namespace Mono.CSharp
                                        Report.Debug (1, "  MERGING JUMP ORIGIN", vector);
 
                                        if (first) {
+                                               if (locals != null && vector.Locals != null)
                                                locals.Or (vector.locals);
+                                               
                                                if (parameters != null)
                                                        parameters.Or (vector.parameters);
                                                first = false;
                                        } else {
+                                               if (locals != null && vector.Locals != null)
                                        locals.And (vector.locals);
                                        if (parameters != null)
                                                parameters.And (vector.parameters);
@@ -779,7 +825,10 @@ namespace Mono.CSharp
                        // </summary>
                        public MyBitVector Locals {
                                get {
+                                       if (locals != null)
                                        return locals.Clone ();
+                                       else
+                                               return null;
                                }
                        }
 
@@ -804,6 +853,8 @@ namespace Mono.CSharp
                                StringBuilder sb = new StringBuilder ();
 
                                sb.Append ("Vector (");
+                               sb.Append (Type);
+                               sb.Append (",");
                                sb.Append (id);
                                sb.Append (",");
                                sb.Append (IsDirty);
@@ -843,6 +894,8 @@ namespace Mono.CSharp
 
                                UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
                                vector = new UsageVector (stype, parent_vector, loc, param_map.Length, local_map.Length);
+                               
+
                        } else {
                                param_map = Parent.param_map;
                                local_map = Parent.local_map;
@@ -885,7 +938,7 @@ namespace Mono.CSharp
                                        continue;
 
                                Report.Error (177, loc, "The out parameter `" +
-                                             param_map.VariableNames [i] + "' must be " +
+                                             var.Name + "' must be " +
                                              "assigned before control leave the current method.");
                        }
                }
@@ -904,10 +957,10 @@ namespace Mono.CSharp
 
                        for (UsageVector child = sibling_list; child != null; child = child.Next) {
                                bool do_break = (Type != BranchingType.Switch) &&
-                                       (Type != BranchingType.LoopBlock);
+                                       (Type != BranchingType.Loop);
                                
                                Report.Debug (2, "    MERGING SIBLING   ", child,
-                                             child.Parameters, child.Locals,
+                                             child.ParameterVector, child.LocalVector,
                                              reachability, child.Reachability, do_break);
 
                                Reachability.And (ref reachability, child.Reachability, do_break);
@@ -949,16 +1002,18 @@ namespace Mono.CSharp
                                // 
                                bool do_break_2 = (child.Type != SiblingType.Block) &&
                                        (child.Type != SiblingType.SwitchSection);
-                               bool unreachable = (do_break_2 && child.Reachability.AlwaysBreaks) ||
-                                       child.Reachability.AlwaysThrows ||
+                               bool always_throws = (child.Type != SiblingType.Try) &&
+                                       child.Reachability.AlwaysThrows;
+                               bool unreachable = always_throws ||
+                                       (do_break_2 && child.Reachability.AlwaysBreaks) ||
                                        child.Reachability.AlwaysReturns ||
                                        child.Reachability.AlwaysHasBarrier;
 
                                Report.Debug (2, "    MERGING SIBLING #1", reachability,
                                              Type, child.Type, child.Reachability.IsUnreachable,
-                                             do_break_2, unreachable);
+                                             do_break_2, always_throws, unreachable);
 
-                               if (!unreachable)
+                               if (!unreachable && (child.LocalVector != null))
                                        MyBitVector.And (ref locals, child.LocalVector);
 
                                // An `out' parameter must be assigned in all branches which do
@@ -1009,10 +1064,73 @@ namespace Mono.CSharp
                        return result.Reachability;
                }
 
-               public virtual bool InTryBlock ()
+               //
+               // Checks whether we're in a `try' block.
+               //
+               public virtual bool InTryOrCatch (bool is_return)
+               {
+                       if ((Block != null) && Block.IsDestructor)
+                               return true;
+                       else if (!is_return &&
+                           ((Type == BranchingType.Loop) || (Type == BranchingType.Switch)))
+                               return false;
+                       else if (Parent != null)
+                               return Parent.InTryOrCatch (is_return);
+                       else
+                               return false;
+               }
+
+               //
+               // Checks whether we're in a `catch' block.
+               //
+               public virtual bool InCatch ()
                {
                        if (Parent != null)
-                               return Parent.InTryBlock ();
+                               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;
+               }
+
+               public virtual bool InLoop ()
+               {
+                       if (Type == BranchingType.Loop)
+                               return true;
+                       else if (Parent != null)
+                               return Parent.InLoop ();
+                       else
+                               return false;
+               }
+
+               public virtual bool InSwitch ()
+               {
+                       if (Type == BranchingType.Switch)
+                               return true;
+                       else if (Parent != null)
+                               return Parent.InSwitch ();
+                       else
+                               return false;
+               }
+
+               public virtual bool BreakCrossesTryCatchBoundary ()
+               {
+                       if ((Type == BranchingType.Loop) || (Type == BranchingType.Switch))
+                               return false;
+                       else if (Parent != null)
+                               return Parent.BreakCrossesTryCatchBoundary ();
                        else
                                return false;
                }
@@ -1021,7 +1139,7 @@ namespace Mono.CSharp
                {
                        if (Parent != null)
                                Parent.AddFinallyVector (vector);
-                       else
+                       else if ((Block == null) || !Block.IsDestructor)
                                throw new NotSupportedException ();
                }
 
@@ -1083,8 +1201,8 @@ namespace Mono.CSharp
        {
                UsageVector sibling_list = null;
 
-               public FlowBranchingBlock (FlowBranching parent, BranchingType type, SiblingType stype,
-                                          Block block, Location loc)
+               public FlowBranchingBlock (FlowBranching parent, BranchingType type,
+                                          SiblingType stype, Block block, Location loc)
                        : base (parent, type, stype, block, loc)
                { }
 
@@ -1121,9 +1239,10 @@ namespace Mono.CSharp
                UsageVector catch_vectors;
                UsageVector finally_vector;
                UsageVector finally_origins;
+               bool in_try;
 
-               public FlowBranchingException (FlowBranching parent, BranchingType type, Block block, Location loc)
-                       : base (parent, type, SiblingType.Try, block, loc)
+               public FlowBranchingException (FlowBranching parent, Block block, Location loc)
+                       : base (parent, BranchingType.Exception, SiblingType.Try, block, loc)
                { }
 
                protected override void AddSibling (UsageVector sibling)
@@ -1131,12 +1250,15 @@ namespace Mono.CSharp
                        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 ();
 
@@ -1147,7 +1269,22 @@ namespace Mono.CSharp
                        get { return current_vector; }
                }
 
-               public override bool InTryBlock ()
+               public override bool InTryOrCatch (bool is_return)
+               {
+                       return finally_vector == null;
+               }
+
+               public override bool InCatch ()
+               {
+                       return !in_try && (finally_vector == null);
+               }
+
+               public override bool InFinally (bool is_return)
+               {
+                       return finally_vector != null;
+               }
+
+               public override bool BreakCrossesTryCatchBoundary ()
                {
                        return true;
                }
@@ -1698,22 +1835,16 @@ namespace Mono.CSharp
                // <summary>
                public readonly int Length;
 
-               // <summary>
-               //   Type and name of all the variables.
-               //   Note that this is null for variables for which we do not need to compute
-               //   assignment info.
-               // </summary>
-               public readonly Type[] VariableTypes;
-               public readonly string[] VariableNames;
-
                VariableInfo[] map;
 
                public VariableMap (InternalParameters ip)
                {
                        Count = ip != null ? ip.Count : 0;
-                       map = new VariableInfo [Count];
-                       VariableNames = new string [Count];
-                       VariableTypes = new Type [Count];
+                       
+                       // Dont bother allocating anything!
+                       if (Count == 0)
+                               return;
+                       
                        Length = 0;
 
                        for (int i = 0; i < Count; i++) {
@@ -1722,10 +1853,13 @@ namespace Mono.CSharp
                                if ((mod & Parameter.Modifier.OUT) == 0)
                                        continue;
 
-                               VariableNames [i] = ip.ParameterName (i);
-                               VariableTypes [i] = TypeManager.GetElementType (ip.ParameterType (i));
+                               // Dont allocate till we find an out var.
+                               if (map == null)
+                                       map = new VariableInfo [Count];
+
+                               map [i] = new VariableInfo (ip.ParameterName (i),
+                                       TypeManager.GetElementType (ip.ParameterType (i)), i, Length);
 
-                               map [i] = new VariableInfo (VariableNames [i], VariableTypes [i], i, Length);
                                Length += map [i].Length;
                        }
                }
@@ -1737,21 +1871,21 @@ namespace Mono.CSharp
                public VariableMap (VariableMap parent, LocalInfo[] locals)
                {
                        int offset = 0, start = 0;
-                       if (parent != null) {
+                       if (parent != null && parent.map != null) {
                                offset = parent.Length;
                                start = parent.Count;
                        }
 
                        Count = locals.Length + start;
+                       
+                       if (Count == 0)
+                               return;
+                       
                        map = new VariableInfo [Count];
-                       VariableNames = new string [Count];
-                       VariableTypes = new Type [Count];
                        Length = offset;
 
-                       if (parent != null) {
+                       if (parent != null && parent.map != null) {
                                parent.map.CopyTo (map, 0);
-                               parent.VariableNames.CopyTo (VariableNames, 0);
-                               parent.VariableTypes.CopyTo (VariableTypes, 0);
                        }
 
                        for (int i = start; i < Count; i++) {
@@ -1760,9 +1894,6 @@ namespace Mono.CSharp
                                if (li.VariableType == null)
                                        continue;
 
-                               VariableNames [i] = li.Name;
-                               VariableTypes [i] = li.VariableType;
-
                                map [i] = li.VariableInfo = new VariableInfo (li, Length);
                                Length += map [i].Length;
                        }
@@ -1774,6 +1905,9 @@ namespace Mono.CSharp
                // </summary>
                public VariableInfo this [int index] {
                        get {
+                               if (map == null)
+                                       return null;
+                               
                                return map [index];
                        }
                }
index 32d12c7a738c30369fe326d6de8a2c566c661b8f..0da03218f3bb7eee96f6dca353b184a896ddd0f1 100644 (file)
@@ -443,8 +443,9 @@ namespace Mono.CSharp {
 
        public class GenericMethod : DeclSpace
        {
-               public GenericMethod (NamespaceEntry ns, TypeContainer parent, string name, Location l)
-                       : base (ns, parent, name, l)
+               public GenericMethod (NamespaceEntry ns, TypeContainer parent, string name,
+                                     Attributes attrs, Location l)
+                       : base (ns, parent, name, attrs, l)
                { }
 
                public override TypeBuilder DefineType ()
index adc5931629322335fdf3c18947d8cb8725cc962f..408b3be4748b45ef2fa66b833c12f03fc7c4ecc5 100755 (executable)
@@ -46,7 +46,6 @@ namespace Mono.CSharp {
                ArrayList property_builders;
                ArrayList event_builders;
                
-               Attributes OptAttributes;
 
                public string IndexerName;
 
@@ -73,10 +72,9 @@ namespace Mono.CSharp {
 
                public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
                                  Attributes attrs, Location l)
-                       : base (ns, parent, name, l)
+                       : base (ns, parent, name, attrs, l)
                {
                        ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
-                       OptAttributes = attrs;
                        
                        method_builders = new ArrayList ();
                        property_builders = new ArrayList ();
index 5fc7523640efdd7ad50ccdea245bc9ac1e9d673a..decfd4612b814e4b41f94110f26c70dbe93c18c8 100644 (file)
@@ -40,11 +40,11 @@ namespace Mono.CSharp {
 
                public static bool CheckContext (EmitContext ec, Location loc)
                {
-                       if (ec.InFinally){
+                       if (ec.CurrentBranching.InFinally (true)){
                                Report.Error (-208, loc, "yield statement can not appear in finally clause");
                                return false;
                        }
-                       if (ec.InCatch){
+                       if (ec.CurrentBranching.InCatch ()){
                                Report.Error (-209, loc, "yield statement can not appear in the catch clause");
                                return false;
                        }
index d491c88dbeb1b27a813a017685903f689e1aadae..f0858fc5f873edf820f8ed50feed6bd9cadd88e0 100755 (executable)
@@ -67,10 +67,8 @@ namespace Mono.CSharp {
 
                static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
                {
-                       if (!(m is MethodInfo))
-                               return false;
-
-                       return ((MethodInfo) m).IsVirtual;
+                       MethodInfo mi = m as MethodInfo;
+                       return (mi == null) ? false : mi.IsVirtual;
                }
 
                /// <summary>
@@ -212,45 +210,39 @@ namespace Mono.CSharp {
                        // Notice that TypeBuilders will only return the interfaces that the Type
                        // is supposed to implement, not all the interfaces that the type implements.
                        //
-                       // Completely broken.  Anyways, we take advantage of this, so we only register
-                       // the implementations that we need, as they are those that are listed by the
-                       // TypeBuilder.
+                       // Even better -- on MS it returns an empty array, no matter what.
+                       //
+                       // Completely broken.  So we do it ourselves!
                        //
-                       Type [] implementing_ifaces = type_builder.GetInterfaces ();
-                       int count = implementing_ifaces.Length;
+                       TypeExpr [] impl = TypeManager.GetExplicitInterfaces (type_builder);
 
-                       if (implementing_ifaces.Length == 0)
+                       if (impl == null || impl.Length == 0)
                                return EmptyMissingInterfacesInfo;
 
-                       MissingInterfacesInfo [] missing_info = new MissingInterfacesInfo [count];
+                       MissingInterfacesInfo [] ret = new MissingInterfacesInfo [impl.Length];
 
-                       for (int i = 0; i < count; i++)
-                               missing_info [i] = new MissingInterfacesInfo (implementing_ifaces [i]);
+                       for (int i = 0; i < impl.Length; i++)
+                               ret [i] = new MissingInterfacesInfo (impl [i].Type);
+
+                       // we really should not get here because Object doesnt implement any
+                       // interfaces. But it could implement something internal, so we have
+                       // to handle that case.
+                       if (type_builder.BaseType == null)
+                               return ret;
                        
+                       TypeExpr [] parent_impls = TypeManager.GetInterfaces (type_builder.BaseType);
                        
-                       //
-                       // Now, we have to extract the interfaces implements by our parents, and
-                       // remove them from the implementing_ifaces array.
-                       //
-                       for (Type t = type_builder.BaseType; t != null; t = t.BaseType){
-                               Type [] base_ifaces = t.GetInterfaces ();
+                       foreach (TypeExpr te in parent_impls) {
+                               Type t = te.Type;
                                        
-                               foreach (Type base_iface in base_ifaces){
-                                       for (int i = 0; i < count; i++){
-                                               if (implementing_ifaces [i] == base_iface)
-                                                       missing_info [i].Optional = true;
+                               for (int i = 0; i < ret.Length; i ++) {
+                                       if (t == ret [i].Type) {
+                                               ret [i].Optional = true;
+                                               break;
                                        }
                                }
-
-                               //
-                               // When we reach a `Type' instead of `TypeBuilder', the GetInterfaces
-                               // call would have returned all of the parent implementations, so we can end.
-                               //
-                               if (!(t is TypeBuilder))
-                                       break;
                        }
-
-                       return missing_info;
+                       return ret;
                }
                
                //
@@ -528,21 +520,18 @@ namespace Mono.CSharp {
                                                if (pending_implementations [i].optional)
                                                        continue;
                                                
-                                               string extra = "";
-                                               
-                                               if (pending_implementations [i].found [j])
-                                                       extra = ".  (method might be non-public or static)";
-                                               Report.Error (
-                                                       536, container.Location,
-                                                       "`" + container.Name + "' does not implement " +
-                                                       "interface member `" +
-                                                       type.FullName + "." + mi.Name + "'" + extra);
+                                               if (pending_implementations [i].found [j]) {
+                                                       string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
+                                                       Report.Error (536, container.Location, "'{0}' does not implement interface member '{1}'. '{2}.{3}' is either static, not public, or has the wrong return type",
+                                                               container.Name, methodLabel, container.Name, methodLabel[methodLabel.Length - 1]);
+                                               }
+                                               else { 
+                                                       Report.Error (535, container.Location, "'{0}' does not implement interface member '{1}'",
+                                                               container.Name, TypeManager.CSharpSignature (mi));
+                                               }
                                        } else {
-                                               Report.Error (
-                                                       534, container.Location,
-                                                       "`" + container.Name + "' does not implement " +
-                                                       "inherited abstract member `" +
-                                                       type.FullName + "." + mi.Name + "'");
+                                               Report.Error (534, container.Location, "'{0}' does not implement inherited abstract member '{1}'",
+                                                       container.Name, TypeManager.CSharpSignature (mi));
                                        }
                                        errors = true;
                                        j++;
index 73461961a48b222f43daba47aeb262a6ad6decd8..e3c1e323ab8cd9fa28e7fe68ea6714c6dcf4f5f0 100755 (executable)
@@ -717,7 +717,7 @@ namespace Mono.CSharp {
                        //
                        if (global_attributes.Count > 0){
                                AssemblyBuilder ab = CodeGen.AssemblyBuilder;
-                               TypeContainer dummy = new TypeContainer (null, null, "", new Location (-1));
+                               TypeContainer dummy = new TypeContainer ();
                                EmitContext temp_ec = new EmitContext (
                                        dummy, Mono.CSharp.Location.Null, null, null, 0, false);
                        
index 3a9b3a603fbb55c7b299a932c8dc9135c3fb196f..b4ff47366bd1219670567d972b7b7b96bdd718ec 100755 (executable)
@@ -21,77 +21,70 @@ namespace Mono.CSharp {
        public abstract class Statement {
                public Location loc;
                
-               ///
+               /// <summary>
                /// Resolves the statement, true means that all sub-statements
                /// did resolve ok.
-               //
+               //  </summary>
                public virtual bool Resolve (EmitContext ec)
                {
                        return true;
                }
                
+               /// <summary>
+               ///   We already know that the statement is unreachable, but we still
+               ///   need to resolve it to catch errors.
+               /// </summary>
+               public virtual bool ResolveUnreachable (EmitContext ec, bool warn)
+               {
+                       //
+                       // This conflicts with csc's way of doing this, but IMHO it's
+                       // the right thing to do.
+                       //
+                       // If something is unreachable, we still check whether it's
+                       // correct.  This means that you cannot use unassigned variables
+                       // in unreachable code, for instance.
+                       //
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
+                       bool ok = Resolve (ec);
+                       ec.KillFlowBranching ();
+
+                       if (!ok)
+                               return false;
+
+                       if (warn)
+                               Report.Warning (162, loc, "Unreachable code detected");
+                       return true;
+               }
+               
                /// <summary>
                ///   Return value indicates whether all code paths emitted return.
                /// </summary>
                protected abstract void DoEmit (EmitContext ec);
 
                /// <summary>
-               ///   Return value indicates whether all code paths emitted return.
+               ///   Utility wrapper routine for Error, just to beautify the code
                /// </summary>
-               public virtual void Emit (EmitContext ec)
+               public void Error (int error, string format, params object[] args)
                {
-                       ec.Mark (loc, true);
-                       DoEmit (ec);
+                       Error (error, String.Format (format, args));
                }
                
-               /// <remarks>
-               ///    Encapsulates the emission of a boolean test and jumping to a
-               ///    destination.
-               ///
-               ///    This will emit the bool expression in `bool_expr' and if
-               ///    `target_is_for_true' is true, then the code will generate a 
-               ///    brtrue to the target.   Otherwise a brfalse. 
-               /// </remarks>
-               public static void EmitBoolExpression (EmitContext ec, Expression bool_expr,
-                                                      Label target, bool target_is_for_true)
+               public void Error (int error, string s)
                {
-                       ILGenerator ig = ec.ig;
-                       
-                       bool invert = false;
-                       if (bool_expr is Unary){
-                               Unary u = (Unary) bool_expr;
-                               
-                               if (u.Oper == Unary.Operator.LogicalNot){
-                                       invert = true;
-
-                                       u.EmitLogicalNot (ec);
-                               }
-                       } else if (bool_expr is Binary){
-                               Binary b = (Binary) bool_expr;
-
-                               if (b.EmitBranchable (ec, target, target_is_for_true))
-                                       return;
-                       }
-
-                       if (!invert)
-                               bool_expr.Emit (ec);
-
-                       if (target_is_for_true){
-                               if (invert)
-                                       ig.Emit (OpCodes.Brfalse, target);
-                               else
-                                       ig.Emit (OpCodes.Brtrue, target);
-                       } else {
-                               if (invert)
-                                       ig.Emit (OpCodes.Brtrue, target);
+                       if (!Location.IsNull (loc))
+                               Report.Error (error, loc, s);
                                else
-                                       ig.Emit (OpCodes.Brfalse, target);
-                       }
+                               Report.Error (error, s);
                }
 
-               public static void Warning_DeadCodeFound (Location loc)
+               /// <summary>
+               ///   Return value indicates whether all code paths emitted return.
+               /// </summary>
+               public virtual void Emit (EmitContext ec)
                {
-                       Report.Warning (162, loc, "Unreachable code detected");
+                       ec.Mark (loc, true);
+                       DoEmit (ec);
                }
        }
 
@@ -145,27 +138,49 @@ namespace Mono.CSharp {
                                return false;
                        }
                        
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
+                       //
+                       // Dead code elimination
+                       //
+                       if (expr is BoolConstant){
+                               bool take = ((BoolConstant) expr).Value;
+
+                               if (take){
+                                       if (!TrueStatement.Resolve (ec))
+                                               return false;
+
+                                       if ((FalseStatement != null) &&
+                                           !FalseStatement.ResolveUnreachable (ec, true))
+                                               return false;
+                                       FalseStatement = null;
+                               } else {
+                                       if (!TrueStatement.ResolveUnreachable (ec, true))
+                                               return false;
+                                       TrueStatement = null;
                        
-                       if (!TrueStatement.Resolve (ec)) {
-                               ec.KillFlowBranching ();
+                                       if ((FalseStatement != null) &&
+                                           !FalseStatement.Resolve (ec))
                                return false;
                        }
 
+                               return true;
+                       }
+                       
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
+                       
+                       bool ok = TrueStatement.Resolve (ec);
+
                        is_true_ret = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
 
                        ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
 
-                       if ((FalseStatement != null) && !FalseStatement.Resolve (ec)) {
-                               ec.KillFlowBranching ();
-                               return false;
-                       }
+                       if ((FalseStatement != null) && !FalseStatement.Resolve (ec))
+                               ok = false;
                                        
                        ec.EndFlowBranching ();
 
                        Report.Debug (1, "END IF BLOCK", loc);
 
-                       return true;
+                       return ok;
                }
                
                protected override void DoEmit (EmitContext ec)
@@ -175,27 +190,21 @@ namespace Mono.CSharp {
                        Label end;
 
                        //
-                       // Dead code elimination
+                       // If we're a boolean expression, Resolve() already
+                       // eliminated dead code for us.
                        //
                        if (expr is BoolConstant){
                                bool take = ((BoolConstant) expr).Value;
 
-                               if (take){
-                                       if (FalseStatement != null){
-                                               Warning_DeadCodeFound (FalseStatement.loc);
-                                       }
+                               if (take)
                                        TrueStatement.Emit (ec);
-                                       return;
-                               } else {
-                                       Warning_DeadCodeFound (TrueStatement.loc);
-                                       if (FalseStatement != null) {
+                               else if (FalseStatement != null)
                                                FalseStatement.Emit (ec);
+
                                                return;
                                        }
-                               }
-                       }
                        
-                       EmitBoolExpression (ec, expr, false_target, false);
+                       expr.EmitBranchable (ec, false_target, false);
 
                        TrueStatement.Emit (ec);
 
@@ -235,7 +244,7 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
 
                        if (!EmbeddedStatement.Resolve (ec))
                                ok = false;
@@ -262,13 +271,9 @@ namespace Mono.CSharp {
                        Label loop = ig.DefineLabel ();
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       bool  old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
                                
                        ig.MarkLabel (loop);
                        EmbeddedStatement.Emit (ec);
@@ -283,21 +288,19 @@ namespace Mono.CSharp {
                                if (res)
                                        ec.ig.Emit (OpCodes.Br, loop); 
                        } else
-                               EmitBoolExpression (ec, expr, loop, true);
+                               expr.EmitBranchable (ec, loop, true);
                        
                        ig.MarkLabel (ec.LoopEnd);
 
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
                }
        }
 
        public class While : Statement {
                public Expression expr;
                public readonly Statement Statement;
-               bool empty, infinite;
+               bool infinite, empty;
                
                public While (Expression boolExpr, Statement statement, Location l)
                {
@@ -314,8 +317,6 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
-
                        //
                        // Inform whether we are infinite or not
                        //
@@ -323,26 +324,21 @@ namespace Mono.CSharp {
                                BoolConstant bc = (BoolConstant) expr;
 
                                if (bc.Value == false){
-                                       Warning_DeadCodeFound (Statement.loc);
+                                       if (!Statement.ResolveUnreachable (ec, true))
+                                               return false;
                                        empty = true;
+                                       return true;
                                } else
                                        infinite = true;
-                       } else {
-                               //
-                               // We are not infinite, so the loop may or may not be executed.
-                               //
-                               ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
                        }
 
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
+
                        if (!Statement.Resolve (ec))
                                ok = false;
 
-                       if (empty)
-                               ec.KillFlowBranching ();
-                       else {
                                ec.CurrentBranching.Infinite = infinite;
                                ec.EndFlowBranching ();
-                       }
 
                        return ok;
                }
@@ -355,13 +351,9 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       bool old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
 
                        //
                        // Inform whether we are infinite or not
@@ -386,14 +378,13 @@ namespace Mono.CSharp {
                        
                                ig.MarkLabel (ec.LoopBegin);
 
-                               EmitBoolExpression (ec, expr, while_loop, true);
+                               expr.EmitBranchable (ec, while_loop, true);
+                               
                                ig.MarkLabel (ec.LoopEnd);
                        }       
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
                }
        }
 
@@ -434,15 +425,20 @@ namespace Mono.CSharp {
                                        BoolConstant bc = (BoolConstant) Test;
 
                                        if (bc.Value == false){
-                                               Warning_DeadCodeFound (Statement.loc);
+                                               if (!Statement.ResolveUnreachable (ec, true))
+                                                       return false;
+                                               if ((Increment != null) &&
+                                                   !Increment.ResolveUnreachable (ec, false))
+                                                       return false;
                                                empty = true;
+                                               return true;
                                        } else
                                                infinite = true;
                                }
                        } else
                                infinite = true;
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                        if (!infinite)
                                ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
 
@@ -454,12 +450,8 @@ namespace Mono.CSharp {
                                        ok = false;
                        }
 
-                       if (empty)
-                               ec.KillFlowBranching ();
-                       else {
                                ec.CurrentBranching.Infinite = infinite;
                                ec.EndFlowBranching ();
-                       }
 
                        return ok;
                }
@@ -472,8 +464,6 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       bool old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        Label loop = ig.DefineLabel ();
                        Label test = ig.DefineLabel ();
                        
@@ -482,8 +472,6 @@ namespace Mono.CSharp {
 
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
 
                        ig.Emit (OpCodes.Br, test);
                        ig.MarkLabel (loop);
@@ -500,21 +488,21 @@ namespace Mono.CSharp {
                        //
                        if (Test != null){
                                //
-                               // The Resolve code already catches the case for Test == BoolConstant (false)
-                               // so we know that this is true
+                               // The Resolve code already catches the case for
+                               // Test == BoolConstant (false) so we know that
+                               // this is true
                                //
                                if (Test is BoolConstant)
                                        ig.Emit (OpCodes.Br, loop);
                                else
-                                       EmitBoolExpression (ec, Test, loop, true);
+                                       Test.EmitBranchable (ec, loop, true);
+                               
                        } else
                                ig.Emit (OpCodes.Br, loop);
                        ig.MarkLabel (ec.LoopEnd);
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
                }
        }
        
@@ -556,24 +544,49 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               bool in_exc;
+
                public override bool Resolve (EmitContext ec)
                {
+                       if (ec.ReturnType == null){
                        if (Expr != null){
+                                       Error (127, "Return with a value not allowed here");
+                                       return false;
+                               }
+                       } else {
+                               if (Expr == null){
+                                       Error (126, "An object of type `{0}' is expected " +
+                                              "for the return statement",
+                                              TypeManager.CSharpName (ec.ReturnType));
+                                       return false;
+                               }
+
                                Expr = Expr.Resolve (ec);
                                if (Expr == null)
                                        return false;
+
+                               if (Expr.Type != ec.ReturnType) {
+                                       Expr = Convert.ImplicitConversionRequired (
+                                               ec, Expr, ec.ReturnType, loc);
+                                       if (Expr == null)
+                                               return false;
+                               }
                        }
 
                        if (ec.InIterator){
-                               Report.Error (-206, loc, "Return statement not allowed inside iterators");
+                               Error (-206, "Return statement not allowed inside iterators");
                                return false;
                        }
                                
                        FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
 
-                       if (ec.CurrentBranching.InTryBlock ())
+                       if (ec.CurrentBranching.InTryOrCatch (true)) {
                                ec.CurrentBranching.AddFinallyVector (vector);
-                       else
+                               in_exc = true;
+                       } else if (ec.CurrentBranching.InFinally (true)) {
+                               Error (157, "Control can not leave the body of the finally block");
+                               return false;
+                       } else
                                vector.CheckOutParameters (ec.CurrentBranching);
 
                        ec.CurrentBranching.CurrentUsageVector.Return ();
@@ -582,46 +595,25 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       if (ec.InFinally){
-                               Report.Error (157, loc, "Control can not leave the body of the finally block");
-                               return;
-                       }
-
-                       if (ec.ReturnType == null){
-                               if (Expr != null){
-                                       Report.Error (127, loc, "Return with a value not allowed here");
-                                       return;
-                               }
-                       } else {
-                               if (Expr == null){
-                                       Report.Error (126, loc, "An object of type `" +
-                                                     TypeManager.CSharpName (ec.ReturnType) + "' is " +
-                                                     "expected for the return statement");
-                                       return;
-                               }
-
-                               if (Expr.Type != ec.ReturnType)
-                                       Expr = Convert.ImplicitConversionRequired (
-                                               ec, Expr, ec.ReturnType, loc);
-
-                               if (Expr == null)
-                                       return;
-
+                       if (Expr != null) {
                                Expr.Emit (ec);
 
-                               if (ec.InTry || ec.InCatch)
+                               if (in_exc || !ec.IsLastStatement)
                                        ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
                        }
 
-                       if (ec.InTry || ec.InCatch) {
-                               if (!ec.HasReturnLabel) {
-                                       ec.ReturnLabel = ec.ig.DefineLabel ();
-                                       ec.HasReturnLabel = true;
-                               }
+                       if (in_exc) {
+                               ec.NeedReturnLabel ();
                                ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
-                       } else {
+                       } else if (ec.IsLastStatement) {
+                               // If we are the last statement in a top-level block, simply
+                               // emit a `ret'.
                                ec.ig.Emit (OpCodes.Ret);
-                               ec.NeedExplicitReturn = false;
+                       } else {
+                               // Otherwise, we always create a return label and jump to
+                               // it.
+                               ec.NeedReturnLabel ();
+                               ec.ig.Emit (OpCodes.Br, ec.ReturnLabel);
                        }
                }
        }
@@ -828,6 +820,9 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
+                       bool in_catch = ec.CurrentBranching.InCatch ();
+                       ec.CurrentBranching.CurrentUsageVector.Throw ();
+
                        if (expr != null){
                                expr = expr.Resolve (ec);
                                if (expr == null)
@@ -846,36 +841,32 @@ namespace Mono.CSharp {
                                if ((t != TypeManager.exception_type) &&
                                    !t.IsSubclassOf (TypeManager.exception_type) &&
                                    !(expr is NullLiteral)) {
-                                       Report.Error (155, loc,
+                                       Error (155,
                                                      "The type caught or thrown must be derived " +
                                                      "from System.Exception");
                                        return false;
                                }
+                       } else if (!in_catch) {
+                               Error (156,
+                                      "A throw statement with no argument is only " +
+                                      "allowed in a catch clause");
+                               return false;
                        }
 
-                       ec.CurrentBranching.CurrentUsageVector.Throw ();
                        return true;
                }
                        
                protected override void DoEmit (EmitContext ec)
                {
-                       if (expr == null){
-                               if (ec.InCatch)
+                       if (expr == null)
                                        ec.ig.Emit (OpCodes.Rethrow);
                                else {
-                                       Report.Error (
-                                               156, loc,
-                                               "A throw statement with no argument is only " +
-                                               "allowed in a catch clause");
-                               }
-                               return;
-                       }
-
                        expr.Emit (ec);
 
                        ec.ig.Emit (OpCodes.Throw);
                }
        }
+       }
 
        public class Break : Statement {
                
@@ -884,8 +875,21 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               bool crossing_exc;
+
                public override bool Resolve (EmitContext ec)
                {
+                       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)) {
+                               Error (157, "Control can not leave the body of the finally block");
+                               return false;
+                       } else if (ec.CurrentBranching.InTryOrCatch (false))
+                               ec.CurrentBranching.AddFinallyVector (ec.CurrentBranching.CurrentUsageVector);
+
+                       crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
+
                        ec.CurrentBranching.CurrentUsageVector.Break ();
                        return true;
                }
@@ -894,17 +898,14 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       if (ec.InLoop == false && ec.Switch == null){
-                               Report.Error (139, loc, "No enclosing loop or switch to continue to");
-                               return;
-                       }
-
-                       if (ec.InTry || ec.InCatch)
+                       if (crossing_exc)
                                ig.Emit (OpCodes.Leave, ec.LoopEnd);
-                       else
+                       else {
+                               ec.NeedReturnLabel ();
                                ig.Emit (OpCodes.Br, ec.LoopEnd);
                }
        }
+       }
 
        public class Continue : Statement {
                
@@ -913,8 +914,21 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               bool crossing_exc;
+
                public override bool Resolve (EmitContext ec)
                {
+                       if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
+                               Error (139, "No enclosing loop to continue to");
+                               return false;
+                       } else if (ec.CurrentBranching.InFinally (false)) {
+                               Error (157, "Control can not leave the body of the finally block");
+                               return false;
+                       } else if (ec.CurrentBranching.InTryOrCatch (false))
+                               ec.CurrentBranching.AddFinallyVector (ec.CurrentBranching.CurrentUsageVector);
+
+                       crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
+
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
@@ -923,26 +937,8 @@ namespace Mono.CSharp {
                {
                        Label begin = ec.LoopBegin;
                        
-                       if (!ec.InLoop){
-                               Report.Error (139, loc, "No enclosing loop to continue to");
-                               return;
-                       } 
-
-                       //
-                       // UGH: Non trivial.  This Br might cross a try/catch boundary
-                       // How can we tell?
-                       //
-                       // while () {
-                       //   try { ... } catch { continue; }
-                       // }
-                       //
-                       // From:
-                       // try {} catch { while () { continue; }}
-                       //
-                       if (ec.TryCatchLevel > ec.LoopBeginTryCatchLevel)
+                       if (crossing_exc)
                                ec.ig.Emit (OpCodes.Leave, begin);
-                       else if (ec.TryCatchLevel < ec.LoopBeginTryCatchLevel)
-                               throw new Exception ("Should never happen");
                        else
                                ec.ig.Emit (OpCodes.Br, begin);
                }
@@ -1074,6 +1070,9 @@ namespace Mono.CSharp {
        ///
        ///   Implicit blocks are used as labels or to introduce variable
        ///   declarations.
+       ///
+       ///   Top-level blocks derive from Block, and they are called ToplevelBlock
+       ///   they contain extra information that is not necessary on normal blocks.
        /// </remarks>
        public class Block : Statement {
                public readonly Block     Parent;
@@ -1086,7 +1085,8 @@ namespace Mono.CSharp {
                        Unchecked = 2,
                        BlockUsed = 4,
                        VariablesInitialized = 8,
-                       HasRet = 16
+                       HasRet = 16,
+                       IsDestructor = 32       
                }
                Flags flags;
 
@@ -1109,6 +1109,7 @@ namespace Mono.CSharp {
                // The statements in this block
                //
                ArrayList statements;
+               int num_statements;
 
                //
                // An array of Blocks.  We keep track of children just
@@ -1526,6 +1527,17 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsDestructor {
+                       get {
+                               return (flags & Flags.IsDestructor) != 0;
+                       }
+               }
+
+               public void SetDestructor ()
+               {
+                       flags |= Flags.IsDestructor;
+               }
+
                VariableMap param_map, local_map;
 
                public VariableMap ParameterMap {
@@ -1707,10 +1719,11 @@ namespace Mono.CSharp {
                                Statement s = (Statement) statements [ix];
                                
                                if (unreachable && !(s is LabeledStatement)) {
-                                       if (!warning_shown && s != EmptyStatement.Value) {
+                                       if (!s.ResolveUnreachable (ec, !warning_shown))
+                                               ok = false;
+
+                                       if (s != EmptyStatement.Value)
                                                warning_shown = true;
-                                               Warning_DeadCodeFound (s.loc);
-                                       }
 
                                        statements [ix] = EmptyStatement.Value;
                                        continue;
@@ -1722,13 +1735,16 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
+                               num_statements = ix + 1;
+
                                if (s is LabeledStatement)
                                        unreachable = false;
                                else
                                        unreachable = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
                        }
 
-                       Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation, ec.CurrentBranching);
+                       Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
+                                     ec.CurrentBranching, statement_count, num_statements);
 
 
                        FlowBranching.UsageVector vector = ec.DoEndFlowBranching ();
@@ -1766,9 +1782,17 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       int statement_count = statements.Count;
-                       for (int ix = 0; ix < statement_count; ix++){
+                       for (int ix = 0; ix < num_statements; ix++){
                                Statement s = (Statement) statements [ix];
+
+                               // Check whether we are the last statement in a
+                               // top-level block.
+
+                               if ((Parent == null) && (ix+1 == num_statements))
+                                       ec.IsLastStatement = true;
+                               else
+                                       ec.IsLastStatement = false;
+
                                s.Emit (ec);
                        }
                }
@@ -1810,6 +1834,20 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // 
+       public class ToplevelBlock : Block {
+               public ToplevelBlock (Parameters parameters, Location start) :
+                       base (null, parameters, start, Location.Null)
+               {
+               }
+
+               public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
+                       base (null, flags, parameters, start, Location.Null)
+               {
+               }
+       }
+       
        public class SwitchLabel {
                Expression label;
                object converted;
@@ -2542,6 +2580,7 @@ namespace Mono.CSharp {
                        ec.Switch = this;
                        ec.Switch.SwitchType = SwitchType;
 
+                       Report.Debug (1, "START OF SWITCH BLOCK", loc, ec.CurrentBranching);
                        ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc);
 
                        bool first = true;
@@ -2559,9 +2598,12 @@ namespace Mono.CSharp {
                        if (!got_default)
                                ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.SwitchSection);
 
-                       ec.EndFlowBranching ();
+                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
                        ec.Switch = old_switch;
 
+                       Report.Debug (1, "END OF SWITCH BLOCK", loc, ec.CurrentBranching,
+                                     reachability);
+
                        return true;
                }
                
@@ -2616,20 +2658,27 @@ namespace Mono.CSharp {
                public override bool Resolve (EmitContext ec)
                {
                        expr = expr.Resolve (ec);
-                       return Statement.Resolve (ec) && expr != null;
+                       if (expr == null)
+                               return false;
+
+                       if (expr.Type.IsValueType){
+                               Error (185, "lock statement requires the expression to be " +
+                                      " a reference type (type is: `{0}'",
+                                      TypeManager.CSharpName (expr.Type));
+                               return false;
+                       }
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Exception, loc);
+                       bool ok = Statement.Resolve (ec);
+                       ec.EndFlowBranching ();
+
+                       return ok;
                }
                
                protected override void DoEmit (EmitContext ec)
                {
                        Type type = expr.Type;
                        
-                       if (type.IsValueType){
-                               Report.Error (185, loc, "lock statement requires the expression to be " +
-                                             " a reference type (type is: `" +
-                                             TypeManager.CSharpName (type) + "'");
-                               return;
-                       }
-
                        ILGenerator ig = ec.ig;
                        LocalBuilder temp = ig.DeclareLocal (type);
                                
@@ -2640,11 +2689,8 @@ namespace Mono.CSharp {
 
                        // try
                        ig.BeginExceptionBlock ();
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
                        Label finish = ig.DefineLabel ();
                        Statement.Emit (ec);
-                       ec.InTry = old_in_try;
                        // ig.Emit (OpCodes.Leave, finish);
 
                        ig.MarkLabel (finish);
@@ -2827,6 +2873,11 @@ namespace Mono.CSharp {
                                // is present, so we need to test for this particular case.
                                //
 
+                               if (e is Cast){
+                                       Report.Error (254, loc, "Cast expression not allowed as right hand expression in fixed statement");
+                                       return false;
+                               }
+                               
                                //
                                // Case 1: & object.
                                //
@@ -2911,7 +2962,21 @@ namespace Mono.CSharp {
                                        data [i].converted = null;
                                        data [i].vi = vi;
                                        i++;
+                                       continue;
+                               }
+
+                               //
+                               // For other cases, flag a `this is already fixed expression'
+                               //
+                               if (e is LocalVariableReference || e is ParameterReference ||
+                                   Convert.ImplicitConversionExists (ec, e, vi.VariableType)){
+                                   
+                                       Report.Error (245, loc, "right hand expression is already fixed, no need to use fixed statement ");
+                                       return false;
                                }
+
+                               Report.Error (245, loc, "Fixed statement only allowed on strings, arrays or address-of expressions");
+                               return false;
                        }
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
@@ -3087,14 +3152,9 @@ namespace Mono.CSharp {
 
                        Report.Debug (1, "START OF TRY BLOCK", Block.StartLocation);
 
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
-
                        if (!Block.Resolve (ec))
                                ok = false;
 
-                       ec.InTry = old_in_try;
-
                        FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
 
                        Report.Debug (1, "START OF CATCH BLOCKS", vector);
@@ -3111,13 +3171,8 @@ namespace Mono.CSharp {
                                        vi.VariableInfo = null;
                                }
 
-                               bool old_in_catch = ec.InCatch;
-                               ec.InCatch = true;
-
                                if (!c.Resolve (ec))
                                        ok = false;
-
-                               ec.InCatch = old_in_catch;
                        }
 
                        Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
@@ -3126,13 +3181,8 @@ namespace Mono.CSharp {
                                ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Catch);
                                Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
 
-                               bool old_in_catch = ec.InCatch;
-                               ec.InCatch = true;
-
                                if (!General.Resolve (ec))
                                        ok = false;
-
-                               ec.InCatch = old_in_catch;
                        }
 
                        Report.Debug (1, "END OF GENERAL CATCH BLOCKS", ec.CurrentBranching);
@@ -3142,13 +3192,8 @@ namespace Mono.CSharp {
                                        ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Finally);
                                Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
 
-                               bool old_in_finally = ec.InFinally;
-                               ec.InFinally = true;
-
                                if (!Fini.Resolve (ec))
                                        ok = false;
-
-                               ec.InFinally = old_in_finally;
                        }
 
                        FlowBranching.Reachability reachability = ec.EndFlowBranching ();
@@ -3162,7 +3207,7 @@ namespace Mono.CSharp {
                                // to the end of the finally block.  This is a problem if `returns'
                                // is true since we may jump to a point after the end of the method.
                                // As a workaround, emit an explicit ret here.
-                               ec.NeedExplicitReturn = true;
+                               ec.NeedReturnLabel ();
                        }
 
                        return ok;
@@ -3173,20 +3218,13 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        Label finish = ig.DefineLabel ();;
 
-                       ec.TryCatchLevel++;
                        ig.BeginExceptionBlock ();
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
                        Block.Emit (ec);
-                       ec.InTry = old_in_try;
 
                        //
                        // System.Reflection.Emit provides this automatically:
                        // ig.Emit (OpCodes.Leave, finish);
 
-                       bool old_in_catch = ec.InCatch;
-                       ec.InCatch = true;
-
                        foreach (Catch c in Specific){
                                LocalInfo vi;
                                
@@ -3209,19 +3247,14 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Pop);
                                General.Block.Emit (ec);
                        }
-                       ec.InCatch = old_in_catch;
 
                        ig.MarkLabel (finish);
                        if (Fini != null){
                                ig.BeginFinallyBlock ();
-                               bool old_in_finally = ec.InFinally;
-                               ec.InFinally = true;
                                Fini.Emit (ec);
-                               ec.InFinally = old_in_finally;
                        }
                        
                        ig.EndExceptionBlock ();
-                       ec.TryCatchLevel--;
                }
        }
 
@@ -3319,18 +3352,13 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        int i = 0;
 
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
                        for (i = 0; i < assign.Length; i++) {
                                assign [i].EmitStatement (ec);
                                
                                ig.BeginExceptionBlock ();
                        }
                        Statement.Emit (ec);
-                       ec.InTry = old_in_try;
 
-                       bool old_in_finally = ec.InFinally;
-                       ec.InFinally = true;
                        var_list.Reverse ();
                        foreach (DictionaryEntry e in var_list){
                                LocalVariableReference var = (LocalVariableReference) e.Key;
@@ -3339,14 +3367,41 @@ namespace Mono.CSharp {
                                
                                ig.BeginFinallyBlock ();
                                
+                               if (!var.Type.IsValueType) {
                                var.Emit (ec);
                                ig.Emit (OpCodes.Brfalse, skip);
                                converted_vars [i].Emit (ec);
                                ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                               } else {
+                                       Expression ml = Expression.MemberLookup(ec, typeof(IDisposable), var.Type, "Dispose", Mono.CSharp.Location.Null);
+
+                                       if (!(ml is MethodGroupExpr)) {
+                                               var.Emit (ec);
+                                               ig.Emit (OpCodes.Box, var.Type);
+                                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                                       } else {
+                                               MethodInfo mi = null;
+
+                                               foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
+                                                       if (mk.GetParameters().Length == 0) {
+                                                               mi = mk;
+                                                               break;
+                                                       }
+                                               }
+
+                                               if (mi == null) {
+                                                       Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+                                                       return false;
+                                               }
+
+                                               var.AddressOf (ec, AddressOp.Load);
+                                               ig.Emit (OpCodes.Call, mi);
+                                       }
+                               }
+
                                ig.MarkLabel (skip);
                                ig.EndExceptionBlock ();
                        }
-                       ec.InFinally = old_in_finally;
 
                        return false;
                }
@@ -3364,21 +3419,16 @@ namespace Mono.CSharp {
                                expr.Emit (ec);
                        ig.Emit (OpCodes.Stloc, local_copy);
 
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
                        ig.BeginExceptionBlock ();
                        Statement.Emit (ec);
-                       ec.InTry = old_in_try;
                        
                        Label skip = ig.DefineLabel ();
-                       bool old_in_finally = ec.InFinally;
                        ig.BeginFinallyBlock ();
                        ig.Emit (OpCodes.Ldloc, local_copy);
                        ig.Emit (OpCodes.Brfalse, skip);
                        ig.Emit (OpCodes.Ldloc, local_copy);
                        ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                        ig.MarkLabel (skip);
-                       ec.InFinally = old_in_finally;
                        ig.EndExceptionBlock ();
 
                        return false;
@@ -3406,7 +3456,7 @@ namespace Mono.CSharp {
                                        return false;
                        }
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Exception, loc);
 
                        bool ok = Statement.Resolve (ec);
 
@@ -3422,7 +3472,7 @@ namespace Mono.CSharp {
                                // to the end of the finally block.  This is a problem if `returns'
                                // is true since we may jump to a point after the end of the method.
                                // As a workaround, emit an explicit ret here.
-                               ec.NeedExplicitReturn = true;
+                               ec.NeedReturnLabel ();
                        }
 
                        return true;
@@ -3501,7 +3551,9 @@ namespace Mono.CSharp {
                                empty = new EmptyExpression (hm.element_type);
                        }
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.LoopBlock, loc);
+                       bool ok = true;
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                        ec.CurrentBranching.CreateSibling (FlowBranching.SiblingType.Conditional);
 
                        //
@@ -3514,18 +3566,25 @@ namespace Mono.CSharp {
                        //
                        conv = Convert.ExplicitConversion (ec, empty, var_type, loc);
                        if (conv == null)
-                               return false;
+                               ok = false;
 
                        variable = variable.ResolveLValue (ec, empty);
                        if (variable == null)
-                               return false;
+                               ok = false;
+
+                       bool disposable = (hm != null) && hm.is_disposable;
+                       if (disposable)
+                               ec.StartFlowBranching (FlowBranching.BranchingType.Exception, loc);
 
                        if (!statement.Resolve (ec))
-                               return false;
+                               ok = false;
+
+                       if (disposable)
+                               ec.EndFlowBranching ();
 
                        ec.EndFlowBranching ();
 
-                       return true;
+                       return ok;
                }
                
                //
@@ -3811,12 +3870,8 @@ namespace Mono.CSharp {
                        // Protect the code in a try/finalize block, so that
                        // if the beast implement IDisposable, we get rid of it
                        //
-                       bool old_in_try = ec.InTry;
-
-                       if (hm.is_disposable) {
+                       if (hm.is_disposable)
                                ig.BeginExceptionBlock ();
-                               ec.InTry = true;
-                       }
                        
                        Label end_try = ig.DefineLabel ();
                        
@@ -3839,7 +3894,6 @@ namespace Mono.CSharp {
                        statement.Emit (ec);
                        ig.Emit (OpCodes.Br, ec.LoopBegin);
                        ig.MarkLabel (end_try);
-                       ec.InTry = old_in_try;
                        
                        // The runtime provides this for us.
                        // ig.Emit (OpCodes.Leave, end);
@@ -3849,8 +3903,6 @@ namespace Mono.CSharp {
                        //
                        if (hm.is_disposable) {
                                Label end_finally = ig.DefineLabel ();
-                               bool old_in_finally = ec.InFinally;
-                               ec.InFinally = true;
                                ig.BeginFinallyBlock ();
 
                                disposable.EmitThis ();
@@ -3864,7 +3916,6 @@ namespace Mono.CSharp {
                                disposable.EmitLoad ();
                                ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                                ig.MarkLabel (end_finally);
-                               ec.InFinally = old_in_finally;
 
                                // The runtime generates this anyways.
                                // ig.Emit (OpCodes.Endfinally);
@@ -4034,12 +4085,8 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
-                       bool old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
                        
                        if (hm != null)
                                EmitCollectionForeach (ec);
@@ -4048,8 +4095,6 @@ namespace Mono.CSharp {
                        
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
                }
        }
 }
index 0f3a2d9244a9c89490a3564e880d1b1d8619836c..17059c13658226243322f563b218435c6c6d33a9 100755 (executable)
@@ -45,7 +45,7 @@ namespace Mono.CSharp
                
                public Tree ()
                {
-                       root_types = new TypeContainer (null, null, "", new Location (-1));
+                       root_types = new TypeContainer ();
 
                        decls = new Hashtable ();
                        namespaces = new Hashtable ();
index f5b51016dd8fefee74797dc8ab5baf0010a4cdee..d37052c1fc2603170fffec34cf391a917ff5920d 100755 (executable)
@@ -513,6 +513,11 @@ public class TypeManager {
        /// </summary>
        public static void AddAssembly (Assembly a)
        {
+               foreach (Assembly assembly in assemblies) {
+                       if (a == assembly)
+                               return;
+               }
+
                int top = assemblies.Length;
                Assembly [] n = new Assembly [top + 1];
 
@@ -781,6 +786,29 @@ public class TypeManager {
                + match.Groups [2].Captures [0].Value;
        }
 
+        /// <summary>
+       ///  Returns the signature of the method with full namespace classification
+       /// </summary>
+       static public string GetFullNameSignature (MemberInfo mi)
+       {
+               return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
+       }
+
+       /// <summary>
+       ///   Returns the signature of the property and indexer
+       /// </summary>
+       static public string CSharpSignature (PropertyBuilder pb, bool is_indexer) 
+       {
+               if (!is_indexer) {
+                       return GetFullNameSignature (pb);
+               }
+
+               MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
+               string signature = GetFullNameSignature (mb);
+               string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
+               return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
+       }
+
         /// <summary>
         ///   Returns the signature of the method
         /// </summary>
@@ -807,7 +835,7 @@ public class TypeManager {
                 }
                 sig += ")";
 
-                return mb.DeclaringType.Name + "." + mb.Name + sig;
+                return GetFullNameSignature (mb) + sig;
         }
 
        /// <summary>
@@ -1832,12 +1860,19 @@ public class TypeManager {
                return ret;
        }
                
+       static PtrHashtable iface_cache = new PtrHashtable ();
+               
        /// <summary>
        ///   This function returns the interfaces in the type `t'.  Works with
        ///   both types and TypeBuilders.
        /// </summary>
        public static TypeExpr [] GetInterfaces (Type t)
        {
+               
+               TypeExpr [] cached = iface_cache [t] as TypeExpr [];
+               if (cached != null)
+                       return cached;
+               
                //
                // The reason for catching the Array case is that Reflection.Emit
                // will not return a TypeBuilder for Array types of TypeBuilder types,
@@ -1867,17 +1902,30 @@ public class TypeManager {
                        parent_ifaces.CopyTo (result, 0);
                        type_ifaces.CopyTo (result, parent_count);
 
+                       iface_cache [t] = result;
                        return result;
                } else {
                        Type [] ifaces = t.GetInterfaces ();
+                       if (ifaces.Length == 0)
+                               return NoTypeExprs;
 
                        TypeExpr [] result = new TypeExpr [ifaces.Length];
                        for (int i = 0; i < ifaces.Length; i++)
                                result [i] = new TypeExpression (ifaces [i], Location.Null);
+                       
+                       iface_cache [t] = result;
                        return result;
                }
        }
        
+       //
+       // gets the interfaces that are declared explicitly on t
+       //
+       public static TypeExpr [] GetExplicitInterfaces (TypeBuilder t)
+       {
+               return (TypeExpr []) builder_to_ifaces [t];
+       }
+       
        /// <remarks>
        ///  The following is used to check if a given type implements an interface.
        ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.