diff options
Diffstat (limited to 'mcs')
-rwxr-xr-x | mcs/class/corlib/System.Reflection.Emit/common.src | 23 | ||||
-rw-r--r-- | mcs/class/corlib/System.Reflection/common.src | 25 | ||||
-rwxr-xr-x | mcs/mcs/ChangeLog | 10303 | ||||
-rwxr-xr-x | mcs/mcs/class.cs | 4737 | ||||
-rwxr-xr-x | mcs/mcs/expression.cs | 7390 |
5 files changed, 0 insertions, 22478 deletions
diff --git a/mcs/class/corlib/System.Reflection.Emit/common.src b/mcs/class/corlib/System.Reflection.Emit/common.src deleted file mode 100755 index 569a9d60748..00000000000 --- a/mcs/class/corlib/System.Reflection.Emit/common.src +++ /dev/null @@ -1,23 +0,0 @@ -AssemblyBuilder.cs -AssemblyBuilderAccess.cs -ConstructorBuilder.cs -EventToken.cs -FieldToken.cs -FlowControl.cs -ILGenerator.cs -Label.cs -MethodToken.cs -ModuleBuilder.cs -OpCode.cs -OpCodes.cs -OpCodeType.cs -OperandType.cs -PackingSize.cs -ParameterToken.cs -PEFileKinds.cs -PropertyToken.cs -SignatureToken.cs -StackBehaviour.cs -StringToken.cs -TypeBuilder.cs -TypeToken.cs diff --git a/mcs/class/corlib/System.Reflection/common.src b/mcs/class/corlib/System.Reflection/common.src deleted file mode 100644 index 022b6768fcc..00000000000 --- a/mcs/class/corlib/System.Reflection/common.src +++ /dev/null @@ -1,25 +0,0 @@ -Assembly.cs -AssemblyNameFlags.cs -BindingFlags.cs -CallingConventions.cs -ConstructorInfo.cs -DefaultMemberAttribute.cs -EventAttributes.cs -EventInfo.cs -FieldAttributes.cs -FieldInfo.cs -ICustomAttributeProvider.cs -MemberFilter.cs -MemberInfo.cs -MemberTypes.cs -MethodAttributes.cs -MethodBase.cs -MethodImplAttributes.cs -MethodInfo.cs -Module.cs -ParameterAttributes.cs -PropertyAttributes.cs -PropertyInfo.cs -ResourceAttributes.cs -ResourceLocation.cs -TypeAttributes.cs diff --git a/mcs/mcs/ChangeLog b/mcs/mcs/ChangeLog deleted file mode 100755 index 50bc4086c41..00000000000 --- a/mcs/mcs/ChangeLog +++ /dev/null @@ -1,10303 +0,0 @@ -2002-12-10 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (ApplyAttributes): Keep track of the emitted - attributes on a per-target basis. This fixes bug #35413. - -2002-12-10 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (MainDriver): On rotor encoding 28591 does not exist, - default to the Windows 1252 encoding. - - (UnixParseOption): Support version, thanks to Alp for the missing - pointer. - - * AssemblyInfo.cs: Add nice assembly information. - - * cs-tokenizer.cs: Add fix from Felix to the #if/#else handler - (bug 35169). - - * cs-parser.jay: Allow a trailing comma before the close bracked - in the attribute_section production. - - * ecore.cs (FieldExpr.AddressOf): Until I figure out why the - address of the instance was being taken, I will take this out, - because we take the address of the object immediately here. - -2002-12-09 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (AreMultipleAllowed): Take care of the most - obvious case where attribute type is not in the current assembly - - stupid me ;-) - -2002-12-08 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (SimpleName.DoResolve): First perform lookups on using - definitions, instead of doing that afterwards. - - Also we use a nice little hack, depending on the constructor, we - know if we are a "composed" name or a simple name. Hence, we - avoid the IndexOf test, and we avoid - - * codegen.cs: Add code to assist in a bug reporter to track down - the source of a compiler crash. - -2002-12-07 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (Attribute.ApplyAttributes) : Keep track of which attribute - types have been emitted for a given element and flag an error - if something which does not have AllowMultiple set is used more - than once. - - * typemanager.cs (RegisterAttributeAllowMultiple): Keep track of - attribute types and their corresponding AllowMultiple properties - - (AreMultipleAllowed): Check the property for a given type. - - * attribute.cs (Attribute.ApplyAttributes): Register the AllowMultiple - property in the case we have a TypeContainer. - - (Attributes.AddAttribute): Detect duplicates and just skip on - adding them. This trivial fix catches a pretty gross error in our - attribute emission - global attributes were being emitted twice! - - Bugzilla bug #33187 is now fixed. - -2002-12-06 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs (pp_expr): Properly recurse here (use pp_expr - instead of pp_and). - - * expression.cs (Binary.ResolveOperator): I can only use the - Concat (string, string, string) and Concat (string, string, - string, string) if the child is actually a concatenation of - strings. - -2002-12-04 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Small fix, because decimal_digits is used in a - context where we need a 2-character lookahead. - - * pending.cs (PendingImplementation): Rework so we can keep track - of interface types all the time, and flag those which were - implemented by parents as optional. - -2002-12-03 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Binary.ResolveOperator): Use - String.Concat(string,string,string) or - String.Concat(string,string,string,string) when possible. - - * typemanager: More helper methods. - - -Tue Dec 3 19:32:04 CET 2002 Paolo Molaro <lupus@ximian.com> - - * pending.cs: remove the bogus return from GetMissingInterfaces() - (see the 2002-11-06 entry: the mono runtime is now fixed in cvs). - -2002-12-02 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * namespace.cs: avoid duplicated 'using xxx' being added to - using_clauses. This prevents mcs from issuing and 'ambiguous type' error - when we get more than one 'using' statement for the same namespace. - Report a CS0105 warning for it. - -2002-11-30 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs (consume_identifier): use read directly, instead - of calling getChar/putback, uses internal knowledge of it. - - (xtoken): Reorder tokenizer so most common patterns are checked - first. This reduces the compilation time in another 5% (from 8.11s - average to 7.73s for bootstrapping mcs on my Mobile p4/1.8ghz). - - The parsing time is 22% of the compilation in mcs, and from that - 64% is spent on the tokenization process. - - I tried using a binary search for keywords, but this is slower - than the hashtable. Another option would be to do a couple of - things: - - * Not use a StringBuilder, instead use an array of chars, - with a set value. Notice that this way we could catch - the 645 error without having to do it *afterwards*. - - * We could write a hand-parser to avoid the hashtable - compares altogether. - - The identifier consumption process takes 37% of the tokenization - time. Another 15% is spent on is_number. 56% of the time spent - on is_number is spent on Int64.Parse: - - * We could probably choose based on the string length to - use Int32.Parse or Int64.Parse and avoid all the 64-bit - computations. - - Another 3% is spend on wrapping `xtoken' in the `token' function. - - Handle 0xa0 as whitespace (#34752) - -2002-11-26 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (IsCLRType): New routine to tell whether a type - is one of the builtin types. - - Maybe it needs to use TypeCodes to be faster. Maybe we could use - typecode in more places instead of doing pointer comparissions. - We could leverage some knowledge about the way the typecodes are - laid out. - - New code to cache namespaces in assemblies, it is currently not - invoked, to be used soon. - - * decl.cs (DeclSpace.MakeFQN): Simple optimization. - - * expression.cs (Binary.ResolveOperator): specially handle - strings, and do not perform user-defined operator overloading for - built-in types. - -2002-11-24 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Avoid calling Char.IsDigit which is an - internalcall as it is a pretty simple operation; Avoid whenever - possible to call Char.IsLetter. - - (consume_identifier): Cut by half the number of - hashtable calls by merging the is_keyword and GetKeyword behavior. - - Do not short-circuit, because if we do, we - report errors (ie, #if false && true would produce an invalid - directive error); - - -2002-11-24 Martin Baulig <martin@ximian.com> - - * expression.cs (Cast.TryReduce): If we're in checked syntax, - check constant ranges and report a CS0221. Fixes #33186. - -2002-11-24 Martin Baulig <martin@ximian.com> - - * cs-parser.jay: Make this work for uninitialized variable - declarations in the `for' initializer. Fixes #32416. - -2002-11-24 Martin Baulig <martin@ximian.com> - - * ecore.cs (Expression.ConvertExplicit): Make casting from/to - System.Enum actually work. Fixes bug #32269, added verify-6.cs. - -2002-11-24 Martin Baulig <martin@ximian.com> - - * expression.cs (Binary.DoNumericPromotions): Added `check_user_conv' - argument; if true, we also check for user-defined conversions. - This is only needed if both arguments are of a user-defined type. - Fixes #30443, added test-175.cs. - (Binary.ForceConversion): Pass the location argument to ConvertImplicit. - - * ecore.cs (Expression.ImplicitUserConversionExists): New method. - -2002-11-24 Martin Baulig <martin@ximian.com> - - * expression.cs (ArrayAccess.GetStoreOpcode): New public static - function to get the store opcode. - (Invocation.EmitParams): Call ArrayAccess.GetStoreOpcode() and - only emit the Ldelema if the store opcode is Stobj. You must run - both test-34 and test-167 to test this. Fixes #34529. - -2002-11-23 Martin Baulig <martin@ximian.com> - - * ecore.cs (Expression.MemberLookup): Added additional - `qualifier_type' argument which is used when we're being called - from MemberAccess.DoResolve() and null if we're called from a - SimpleName lookup. - (Expression.MemberLookupFailed): New method to report errors; this - does the CS1540 check and reports the correct error message. - - * typemanager.cs (MemberLookup): Added additional `qualifier_type' - argument for the CS1540 check and redone the way how we're dealing - with private members. See the comment in the source code for details. - (FilterWithClosure): Reverted this back to revision 1.197; renamed - `closure_start_type' to `closure_qualifier_type' and check whether - it's not null. It was not this filter being broken, it was just - being called with the wrong arguments. - - * expression.cs (MemberAccess.DoResolve): use MemberLookupFinal() - and pass it the correct `qualifier_type'; this also does the error - handling for us. - -2002-11-22 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Invocation.EmitParams): If the we are dealing - with a non-built-in value type, load its address as well. - - (ArrayCreation): Use a a pretty constant instead - of the hardcoded value 2. Use 6 instead of 2 for the number of - static initializers. - - (ArrayCreation.EmitDynamicInitializers): Peel enumerations, - because they are not really value types, just glorified integers. - - * driver.cs: Do not append .exe, the CSC compiler does not do it. - - * ecore.cs: Remove redundant code for enumerations, make them use - the same code path as everything else, fixes the casting issue - with enumerations in Windows.Forms. - - * attribute.cs: Do only cast to string if it is a string, the - validation happens later. - - * typemanager.cs: Temproary hack to avoid a bootstrap issue until - people upgrade their corlibs. - - * ecore.cs: Oops, enumerations were not following the entire code path - -2002-11-21 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (FilterWithClosure): Commented out the test for - 1540 in typemanager.cs, as it has problems when accessing - protected methods from a parent class (see test-174.cs). - - * attribute.cs (Attribute.ValidateGuid): new method. - (Attribute.Resolve): Use above. - -2002-11-19 Miguel de Icaza <miguel@ximian.com> - - * enum.cs: In FindMembers, perform a recursive lookup for values. (34308) - - * ecore.cs (SimpleName.SimpleNameResolve): Remove the special - handling for enumerations, as we only needed the TypeContainer - functionality to begin with (this is required for the fix below to - work for enums that reference constants in a container class for - example). - - * codegen.cs (EmitContext): Make TypeContainer a DeclSpace. - - * enum.cs (Enum.Define): Use `this' instead of parent, so we have - a valid TypeBuilder to perform lookups on.o - - * class.cs (InheritableMemberSignatureCompare): Use true in the - call to GetGetMethod and GetSetMethod, because we are comparing - the signature, and we need to get the methods *even* if they are - private. - - (PropertyBase.CheckBase): ditto. - - * statement.cs (Switch.ResolveAndReduce, Block.EmitMeta, - GotoCase.Resolve): Use Peel on EmpytCasts. - - * ecore.cs (EmptyCast): drop child, add Peel method. - -2002-11-17 Martin Baulig <martin@ximian.com> - - * ecore.cs (EmptyCast.Child): New public property. - - * statement.cs (SwitchLabel.ResolveAndReduce): Check whether the - label resolved to an EmptyCast. Fixes #34162. - (GotoCase.Resolve): Likewise. - (Block.EmitMeta): Likewise. - -2002-11-17 Martin Baulig <martin@ximian.com> - - * expression.cs (Invocation.BetterConversion): Prefer int over - uint; short over ushort; long over ulong for integer literals. - Use ImplicitConversionExists instead of StandardConversionExists - since we also need to check for user-defined implicit conversions. - Fixes #34165. Added test-173.cs. - -2002-11-16 Martin Baulig <martin@ximian.com> - - * expression.cs (Binary.EmitBranchable): Eliminate comparisions - with the `true' and `false' literals. Fixes #33151. - -2002-11-16 Martin Baulig <martin@ximian.com> - - * typemanager.cs (RealMemberLookup): Reverted Miguel's patch from - October 22nd; don't do the cs1540 check for static members. - - * ecore.cs (PropertyExpr.ResolveAccessors): Rewrote this; we're - now using our own filter here and doing the cs1540 check again. - -2002-11-16 Martin Baulig <martin@ximian.com> - - * support.cs (InternalParameters): Don't crash if we don't have - any fixed parameters. Fixes #33532. - -2002-11-16 Martin Baulig <martin@ximian.com> - - * decl.cs (MemberCache.AddMethods): Use BindingFlags.FlattenHierarchy - when looking up static methods to make this work on Windows. - Fixes #33773. - -2002-11-16 Martin Baulig <martin@ximian.com> - - * ecore.cs (PropertyExpr.VerifyAssignable): Check whether we have - a setter rather than using PropertyInfo.CanWrite. - -2002-11-15 Nick Drochak <ndrochak@gol.com> - - * class.cs: Allow acces to block member by subclasses. Fixes build - breaker. - -2002-11-14 Martin Baulig <martin@ximian.com> - - * class.cs (Constructor.Emit): Added the extern/block check. - Fixes bug #33678. - -2002-11-14 Martin Baulig <martin@ximian.com> - - * expression.cs (IndexerAccess.DoResolve): Do a DeclaredOnly - iteration while looking for indexers, this is needed because the - indexer may have a different name in our base classes. Fixed the - error reporting (no indexers at all, not get accessor, no - overloaded match). Fixes bug #33089. - (IndexerAccess.DoResolveLValue): Likewise. - -2002-11-14 Martin Baulig <martin@ximian.com> - - * class.cs (PropertyBase.CheckBase): Make this work for multiple - indexers. Fixes the first part of bug #33089. - (MethodSignature.InheritableMemberSignatureCompare): Added support - for properties. - -2002-11-13 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (Attribute.Resolve): Catch the - NullReferenceException and report it since it isn't supposed to - happen. - -2002-11-12 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Binary.EmitBranchable): Also handle the cases for - LogicalOr and LogicalAnd that can benefit from recursively - handling EmitBranchable. The code now should be nice for Paolo. - -2002-11-08 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (LookupType): Added a negative-hit hashtable for - the Type lookups, as we perform quite a number of lookups on - non-Types. This can be removed once we can deterministically tell - whether we have a type or a namespace in advance. - - But this might require special hacks from our corlib. - - * TODO: updated. - - * ecore.cs (TryImplicitIntConversion): Handle conversions to float - and double which avoids a conversion from an integer to a double. - - * expression.cs: tiny optimization, avoid calling IsConstant, - because it effectively performs the lookup twice. - -2002-11-06 Miguel de Icaza <miguel@ximian.com> - - But a bogus return here to keep the semantics of the old code - until the Mono runtime is fixed. - - * pending.cs (GetMissingInterfaces): New method used to remove all - the interfaces that are already implemented by our parent - classes from the list of pending methods. - - * interface.cs: Add checks for calls after ResolveTypeExpr. - -2002-11-05 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Class.Emit): Report warning 67: event not used if the - warning level is beyond 3. - - * ecore.cs (Expression.ConvertExplicit): Missed a check for expr - being a NullLiteral. - - * cs-parser.jay: Fix, Gonzalo reverted the order of the rank - specifiers. - - * class.cs (TypeContainer.GetClassBases): Cover a missing code - path that might fail if a type can not be resolved. - - * expression.cs (Binary.Emit): Emit unsigned versions of the - operators. - - * driver.cs: use error 5. - -2002-11-02 Gonzalo Paniagua Javier <gonzalo@gnome-db.org> - - * cs-parser.jay: simplified a rule and 5 SR conflicts dissapeared. - -2002-11-01 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay (switch_section): A beautiful patch from Martin - Baulig that fixed 33094. - -2002-10-31 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (PropertyExpr.DoResolveLValue, PropertyExpr.DoResolve): - Check whether the base is abstract and report an error if so. - - * expression.cs (IndexerAccess.DoResolveLValue, - IndexerAccess.DoResolve): ditto. - - (Invocation.DoResolve): ditto. - - (Invocation.FullMethodDesc): Improve the report string. - - * statement.cs (Block): Eliminate IsVariableDefined as it is - basically just a wrapper for GetVariableInfo. - - * ecore.cs (SimpleName): Use new - - * support.cs (ReflectionParamter.ParameterType): We unwrap the - type, as we return the actual parameter ref/unref state on a - different call. - -2002-10-30 Miguel de Icaza <miguel@ximian.com> - - * support.cs: Return proper flags REF/OUT fixing the previous - commit. - - * expression.cs: Reverted last patch, that was wrong. Is_ref is - not used to mean `ref' but `ref or out' in ParameterReference - - * delegate.cs (FullDelegateDesc): use ParameterDesc to get the - full type signature instead of calling TypeManger.CSharpName - ourselves. - - * support.cs (InternalParameters.ParameterDesc): Do not compare - directly to the modflags, because REF/OUT will actually be bitsets - if set. - - * delegate.cs (VerifyMethod): Check also the modifiers. - - * cs-tokenizer.cs: Fix bug where floating point values with an - exponent where a sign was missing was ignored. - - * driver.cs: Allow multiple assemblies to be specified in a single - /r: argument - -2002-10-28 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Ugly. We had to add a multiplicative_expression, - because identifiers after a parenthesis would end up in this kind - of production, and we needed to desamiguate it for having casts - like: - - (UserDefinedType *) xxx - -2002-10-24 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (RealMemberLookup): when we deal with a subclass, - we should set on the Bindingflags.NonPublic, but not turn on - private_ok. private_ok controls whether a Private member is - returned (this is chekced on the filter routine), while the - BindingFlags.NonPublic just controls whether private/protected - will be allowed. This fixes the problem part of the problem of - private properties being allowed to be used in derived classes. - - * expression.cs (BaseAccess): Provide an DoResolveLValue method, - so we can call the children DoResolveLValue method (this will - properly signal errors on lvalue assignments to base properties) - - * ecore.cs (PropertyExpr.ResolveAccessors): If both setter and - getter are null, and we have a property info, we know that this - happened because the lookup failed, so we report an error 122 for - protection level violation. - - We also silently return if setter and getter are null in the - resolve functions, this condition only happens if we have flagged - the error before. This is the other half of the problem. - - (PropertyExpr.ResolveAccessors): Turns out that PropertyInfo does - not have accessibility information, that is why we were returning - true in the filter function in typemanager.cs. - - To properly report 122 (property is inaccessible because of its - protection level) correctly, we report this error in ResolveAccess - by failing if both the setter and the getter are lacking (ie, the - lookup failed). - - DoResolve and DoLResolve have been modified to check for both - setter/getter being null and returning silently, the reason being - that I did not want to put the knowledge about this error in upper - layers, like: - - int old = Report.Errors; - x = new PropertyExpr (...); - if (old != Report.Errors) - return null; - else - return x; - - So the property expr is returned, but it is invalid, so the error - will be flagged during the resolve process. - - * class.cs: Remove InheritablePropertySignatureCompare from the - class, as we no longer depend on the property signature to compute - whether it is possible to implement a method or not. - - The reason is that calling PropertyInfo.GetGetMethod will return - null (in .NET, in Mono it works, and we should change this), in - cases where the Get Method does not exist in that particular - class. - - So this code: - - class X { public virtual int A { get { return 1; } } } - class Y : X { } - class Z : Y { public override int A { get { return 2; } } } - - Would fail in Z because the parent (Y) would not have the property - defined. So we avoid this completely now (because the alternative - fix was ugly and slow), and we now depend exclusively on the - method names. - - (PropertyBase.CheckBase): Use a method-base mechanism to find our - reference method, instead of using the property. - - * typemanager.cs (GetPropertyGetter, GetPropertySetter): These - routines are gone now. - - * typemanager.cs (GetPropertyGetter, GetPropertySetter): swap the - names, they were incorrectly named. - - * cs-tokenizer.cs: Return are more gentle token on failure. - - * pending.cs (PendingImplementation.InterfaceMethod): This routine - had an out-of-sync index variable, which caused it to remove from - the list of pending methods the wrong method sometimes. - -2002-10-22 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (PropertyExpr): Do not use PropertyInfo.CanRead, - CanWrite, because those refer to this particular instance of the - property, and do not take into account the fact that we can - override single members of a property. - - Constructor requires an EmitContext. The resolution process does - not happen here, but we need to compute the accessors before, - because the resolution does not always happen for properties. - - * typemanager.cs (RealMemberLookup): Set private_ok if we are a - subclass, before we did not update this flag, but we did update - bindingflags. - - (GetAccessors): Drop this routine, as it did not work in the - presence of partially overwritten set/get methods. - - Notice that this broke the cs1540 detection, but that will require - more thinking. - -2002-10-22 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * class.cs: - * codegen.cs: - * driver.cs: issue a warning instead of an error if we don't support - debugging for the platform. Also ignore a couple of errors that may - arise when trying to write the symbols. Undo my previous patch. - -2002-10-22 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * driver.cs: ignore /debug switch except for Unix platforms. - -2002-10-23 Nick Drochak <ndrochak@gol.com> - - * makefile: Remove mcs2.exe and mcs3.exe on 'make clean' - -2002-10-21 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Do not make mcs-debug conditional, so we do not break - builds that use it. - - * statement.cs (UsageVector.MergeChildren): I would like Martin to - review this patch. But basically after all the children variables - have been merged, the value of "Breaks" was not being set to - new_breaks for Switch blocks. I think that it should be set after - it has executed. Currently I set this to the value of new_breaks, - but only if new_breaks is FlowReturn.ALWAYS, which is a bit - conservative, but I do not understand this code very well. - - I did not break anything in the build, so that is good ;-) - - * cs-tokenizer.cs: Also allow \r in comments as a line separator. - -2002-10-20 Mark Crichton <crichton@gimp.org> - - * cfold.cs: Fixed compile blocker. Really fixed it this time. - -2002-10-20 Nick Drochak <ndrochak@gol.com> - - * cfold.cs: Fixed compile blocker. - -2002-10-20 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: I was chekcing the key, not the file. - -2002-10-19 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (UserDefinedConversion): Get rid of the bogus error - message that we were generating - we just need to silently return - a null. - -2002-10-19 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Event.Define): Change my previous commit, as this - breaks the debugger. This is a temporary hack, as it seems like - the compiler is generating events incorrectly to begin with. - - * expression.cs (Binary.ResolveOperator): Added support for - "U operator - (E x, E y)" - - * cfold.cs (BinaryFold): Added support for "U operator - (E x, E - y)". - - * ecore.cs (FieldExpr.AddressOf): We had a special code path for - init-only variables, but this path did not take into account that - there might be also instance readonly variables. Correct this - problem. - - This fixes bug 32253 - - * delegate.cs (NewDelegate.DoResolve): Catch creation of unsafe - delegates as well. - - * driver.cs: Change the extension for modules to `netmodule' - - * cs-parser.jay: Improved slightly the location tracking for - the debugger symbols. - - * class.cs (Event.Define): Use Modifiers.FieldAttr on the - modifiers that were specified instead of the hardcoded value - (FamAndAssem). This was basically ignoring the static modifier, - and others. Fixes 32429. - - * statement.cs (Switch.SimpleSwitchEmit): Simplified the code, and - fixed a bug in the process (32476) - - * expression.cs (ArrayAccess.EmitAssign): Patch from - hwang_rob@yahoo.ca that fixes bug 31834.3 - -2002-10-18 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Make the module extension .netmodule. - -2002-10-16 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Report an error if the resource file is not found - instead of crashing. - - * ecore.cs (PropertyExpr.EmitAssign): Pass IsBase instead of - false, like Emit does. - -2002-10-16 Nick Drochak <ndrochak@gol.com> - - * typemanager.cs: Remove unused private member. Also reported mcs - bug to report this as a warning like csc. - -2002-10-15 Martin Baulig <martin@gnome.org> - - * statement.cs (Statement.Emit): Made this a virtual method; emits - the line number info and calls DoEmit(). - (Statement.DoEmit): New protected abstract method, formerly knows - as Statement.Emit(). - - * codegen.cs (EmitContext.Mark): Check whether we have a symbol writer. - -2002-10-11 Miguel de Icaza <miguel@ximian.com> - - * class.cs: Following the comment from 2002-09-26 to AddMethod, I - have fixed a remaining problem: not every AddXXXX was adding a - fully qualified name. - - Now everyone registers a fully qualified name in the DeclSpace as - being defined instead of the partial name. - - Downsides: we are slower than we need to be due to the excess - copies and the names being registered this way. - - The reason for this is that we currently depend (on the corlib - bootstrap for instance) that types are fully qualified, because - we dump all the types in the namespace, and we should really have - types inserted into the proper namespace, so we can only store the - basenames in the defined_names array. - -2002-10-10 Martin Baulig <martin@gnome.org> - - * expression.cs (ArrayAccess.EmitStoreOpcode): Reverted the patch - from bug #31834, see the bug report for a testcase which is - miscompiled. - -2002-10-10 Martin Baulig <martin@gnome.org> - - * codegen.cs (EmitContext.Breaks): Removed, we're now using the - flow analysis code for this. - - * statement.cs (Do, While, For): Tell the flow analysis code about - infinite loops. - (FlowBranching.UsageVector): Added support for infinite loops. - (Block.Resolve): Moved the dead code elimination here and use flow - analysis to do it. - -2002-10-09 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Field.Define): Catch cycles on struct type - definitions. - - * typemanager.cs (IsUnmanagedtype): Do not recursively check - fields if the fields are static. We only need to check instance - fields. - - * expression.cs (As.DoResolve): Test for reference type. - - * statement.cs (Using.ResolveExpression): Use - ConvertImplicitRequired, not ConvertImplicit which reports an - error on failture - (Using.ResolveLocalVariableDecls): ditto. - - * expression.cs (Binary.ResolveOperator): Report errors in a few - places where we had to. - - * typemanager.cs (IsUnmanagedtype): Finish implementation. - -2002-10-08 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Use StoreFromPtr instead of extracting the type - and then trying to use Stelem. Patch is from hwang_rob@yahoo.ca - - * ecore.cs (ImplicitReferenceConversion): It is possible to assign - an enumeration value to a System.Enum, but System.Enum is not a - value type, but an class type, so we need to box. - - (Expression.ConvertExplicit): One codepath could return - errors but not flag them. Fix this. Fixes #31853 - - * parameter.cs (Resolve): Do not allow void as a parameter type. - -2002-10-06 Martin Baulig <martin@gnome.org> - - * statemenc.cs (FlowBranching.SetParameterAssigned): Don't crash - if it's a class type and not a struct. Fixes #31815. - -2002-10-06 Martin Baulig <martin@gnome.org> - - * statement.cs: Reworked the flow analysis code a bit to make it - usable for dead code elimination. - -2002-10-06 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * cs-parser.jay: allow empty source files. Fixes bug #31781. - -2002-10-04 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ComposedCast.DoResolveType): A quick workaround - to fix the test 165, will investigate deeper. - -2002-10-04 Martin Baulig <martin@gnome.org> - - * statement.cs (FlowBranching.UsageVector.MergeChildren): Make - finally blocks actually work. - (Try.Resolve): We don't need to create a sibling for `finally' if - there is no finally block. - -2002-10-04 Martin Baulig <martin@gnome.org> - - * class.cs (Constructor.Define): The default accessibility for a - non-default constructor is private, not public. - -2002-10-04 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Constructor): Make AllowedModifiers public, add - EXTERN. - - * cs-parser.jay: Perform the modifiers test here, as the - constructor for the Constructor class usually receives a zero - because of the way we create it (first we create, later we - customize, and we were never checking the modifiers). - - * typemanager.cs (Typemanager.LookupTypeDirect): This new function - is a version of LookupTypeReflection that includes the type-name - cache. This can be used as a fast path for functions that know - the fully qualified name and are only calling into *.GetType() to - obtain a composed type. - - This is also used by TypeManager.LookupType during its type - composition. - - (LookupType): We now also track the real type name, as sometimes - we can get a quey for the real type name from things like - ComposedCast. This fixes bug 31422. - - * expression.cs (ComposedCast.Resolve): Since we are obtaining a - complete type fullname, it does not have to go through the type - resolution system to obtain the composed version of the type (for - obtaining arrays or pointers). - - (Conditional.Emit): Use the EmitBoolExpression to - generate nicer code, as requested by Paolo. - - (ArrayCreation.CheckIndices): Use the patch from - hwang_rob@yahoo.ca to validate the array initializers. - -2002-10-03 Miguel de Icaza <miguel@ximian.com> - - * class.cs (ConstructorInitializer.Emit): simplify code by using - Invocation.EmitCall, and at the same time, fix the bugs in calling - parent constructors that took variable arguments. - - * ecore.cs (Expression.ConvertNumericExplicit, - Expression.ImplicitNumericConversion): Remove the code that - manually wrapped decimal (InternalTypeConstructor call is now gone - as well). - - * expression.cs (Cast.TryReduce): Also handle decimal types when - trying to perform a constant fold on the type. - - * typemanager.cs (IsUnmanagedtype): Partially implemented. - - * parameter.cs: Removed ResolveAndDefine, as it was not needed, as - that only turned off an error report, and did nothing else. - -2002-10-02 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Handle and ignore /fullpaths - -2002-10-01 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Binary.ResolveOperator): Catch the case where - DoNumericPromotions returns true, - - (Binary.DoNumericPromotions): Simplify the code, and the tests. - -2002-09-27 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (EventExpr.Emit): Instead of emitting an exception, - report error 70. - -2002-09-26 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (ConvertNumericExplicit): It is not enough that the - conversion exists, but it is also required that the conversion be - performed. This manifested in "(Type64Enum) 2". - - * class.cs (TypeManager.AddMethod): The fix is not to change - AddEnum, because that one was using a fully qualified name (every - DeclSpace derivative does), but to change the AddMethod routine - that was using an un-namespaced name. This now correctly reports - the duplicated name. - - Revert patch until I can properly fix it. The issue - is that we have a shared Type space across all namespaces - currently, which is wrong. - - Options include making the Namespace a DeclSpace, and merge - current_namespace/current_container in the parser. - -2002-09-25 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Improve error reporting when we get a different - kind of expression in local_variable_type and - local_variable_pointer_type. - - Propagate this to avoid missleading errors being reported. - - * ecore.cs (ImplicitReferenceConversion): treat - TypeManager.value_type as a target just like object_type. As - code like this: - - ValueType v = 1; - - Is valid, and needs to result in the int 1 being boxed before it - is assigned to the value type v. - - * class.cs (TypeContainer.AddEnum): Use the basename, not the name - to validate the enumeration name. - - * expression.cs (ArrayAccess.EmitAssign): Mimic the same test from - EmitDynamicInitializers for the criteria to use Ldelema. Thanks - to hwang_rob@yahoo.ca for finding the bug and providing a patch. - - * ecore.cs (TryImplicitIntConversion): When doing an - implicit-enumeration-conversion, check if the type is 64-bits and - perform a conversion before passing to EnumConstant. - -2002-09-23 Miguel de Icaza <miguel@ximian.com> - - * decl.cs (Error_AmbiguousTypeReference); New routine used to - report ambiguous type references. Unlike the MS version, we - report what the ambiguity is. Innovation at work ;-) - - (DeclSpace.FindType): Require a location argument to - display when we display an ambiguous error. - - * ecore.cs: (SimpleName.DoResolveType): Pass location to FindType. - - * interface.cs (GetInterfaceTypeByName): Pass location to FindType. - - * expression.cs (EmitDynamicInitializers): Apply patch from - hwang_rob@yahoo.ca that fixes the order in which we emit our - initializers. - -2002-09-21 Martin Baulig <martin@gnome.org> - - * delegate.cs (Delegate.VerifyApplicability): Make this work if the - delegate takes no arguments. - -2002-09-20 Miguel de Icaza <miguel@ximian.com> - - * constant.cs: Use Conv_U8 instead of Conv_I8 when loading longs - from integers. - - * expression.cs: Extract the underlying type. - - * ecore.cs (StoreFromPtr): Use TypeManager.IsEnumType instad of IsEnum - - * decl.cs (FindType): Sorry about this, fixed the type lookup bug. - -2002-09-19 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer.DefineType): We can not use the nice - PackingSize with the size set to 1 DefineType method, because it - will not allow us to define the interfaces that the struct - implements. - - This completes the fixing of bug 27287 - - * ecore.cs (Expresion.ImplicitReferenceConversion): `class-type S' - means also structs. This fixes part of the problem. - (Expresion.ImplicitReferenceConversionExists): ditto. - - * decl.cs (DeclSparce.ResolveType): Only report the type-not-found - error if there were no errors reported during the type lookup - process, to avoid duplicates or redundant errors. Without this - you would get an ambiguous errors plus a type not found. We have - beaten the user enough with the first error. - - (DeclSparce.FindType): Emit a warning if we have an ambiguous - reference. - - * ecore.cs (SimpleName.DoResolveType): If an error is emitted - during the resolution process, stop the lookup, this avoids - repeated error reports (same error twice). - - * rootcontext.cs: Emit a warning if we have an ambiguous reference. - - * typemanager.cs (LookupType): Redo the type lookup code to match - the needs of System.Reflection. - - The issue is that System.Reflection requires references to nested - types to begin with a "+" sign instead of a dot. So toplevel - types look like: "NameSpace.TopLevelClass", and nested ones look - like "Namespace.TopLevelClass+Nested", with arbitrary nesting - levels. - -2002-09-19 Martin Baulig <martin@gnome.org> - - * codegen.cs (EmitContext.EmitTopBlock): If control flow analysis - says that a method always returns or always throws an exception, - don't report the CS0161. - - * statement.cs (FlowBranching.UsageVector.MergeChildren): Always - set `Returns = new_returns'. - -2002-09-19 Martin Baulig <martin@gnome.org> - - * expression.cs (MemberAccess.ResolveMemberAccess): When resolving - to an enum constant, check for a CS0176. - -2002-09-18 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer.CheckPairedOperators): Now we check - for operators that must be in pairs and report errors. - - * ecore.cs (SimpleName.DoResolveType): During the initial type - resolution process, when we define types recursively, we must - check first for types in our current scope before we perform - lookups in the enclosing scopes. - - * expression.cs (MakeByteBlob): Handle Decimal blobs. - - (Invocation.VerifyArgumentsCompat): Call - TypeManager.TypeToCoreType on the parameter_type.GetElementType. - I thought we were supposed to always call this, but there are a - few places in the code where we dont do it. - -2002-09-17 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Add support in -linkres and -resource to specify the - name of the identifier. - -2002-09-16 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (StandardConversionExists): Sync with the conversion - code: allow anything-* to void* conversions. - - (FindMostSpecificSource): Use an Expression argument - instead of a Type, because we might be handed over a Literal which - gets a few more implicit conversions that plain types do not. So - this information was being lost. - - Also, we drop the temporary type-holder expression when not - required. - -2002-09-17 Martin Baulig <martin@gnome.org> - - * class.cs (PropertyBase.CheckBase): Don't check the base class if - this is an explicit interface implementation. - -2002-09-17 Martin Baulig <martin@gnome.org> - - * class.cs (PropertyBase.CheckBase): Make this work for indexers with - different `IndexerName' attributes. - - * expression.cs (BaseIndexerAccess): Rewrote this class to use IndexerAccess. - (IndexerAccess): Added special protected ctor for BaseIndexerAccess and - virtual CommonResolve(). - -2002-09-16 Miguel de Icaza <miguel@ximian.com> - - * enum.cs (LookupEnumValue): Use the EnumConstant declared type, - and convert that to the UnderlyingType. - - * statement.cs (Foreach.Resolve): Indexers are just like variables - or PropertyAccesses. - - * cs-tokenizer.cs (consume_string): Track line numbers and columns - inside quoted strings, we were not doing this before. - -2002-09-16 Martin Baulig <martin@gnome.org> - - * ecore.cs (MethodGroupExpr.DoResolve): If we have an instance expression, - resolve it. This is needed for the definite assignment check of the - instance expression, fixes bug #29846. - (PropertyExpr.DoResolve, EventExpr.DoResolve): Likewise. - -2002-09-16 Nick Drochak <ndrochak@gol.com> - - * parameter.cs: Fix compile error. Cannot reference static member - from an instance object. Is this an mcs bug? - -2002-09-14 Martin Baulig <martin@gnome.org> - - * decl.cs (MemberCache.SetupCacheForInterface): Don't add an interface - multiple times. Fixes bug #30295, added test-166.cs. - -2002-09-14 Martin Baulig <martin@gnome.org> - - * statement.cs (Block.Emit): Don't emit unreachable code. - (Switch.SimpleSwitchEmit, Switch.TableSwitchEmit): Check for missing - `break' statements. - (Goto.Emit, Continue.Emit): Set ec.Breaks = true. - -2002-09-14 Martin Baulig <martin@gnome.org> - - * parameter.cs (Parameter.Attributes): Make this work if Modifier.ISBYREF - is set. - -2002-09-14 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.IsNestedChildOf): This must return false - if `type == parent' since in this case `type.IsSubclassOf (parent)' will - be false on the ms runtime. - -2002-09-13 Martin Baulig <martin@gnome.org> - - * ecore.cs (SimpleName.SimpleNameResolve): Include the member name in - the CS0038 error message. - -2002-09-12 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (CheckedExpr, UnCheckedExpr): If we have a - constant inside, return it. - -2002-09-12 Martin Baulig <martin@gnome.org> - - * cfold.cs (ConstantFold.DoConstantNumericPromotions): Check whether an - implicit conversion can be done between enum types. - - * enum.cs (Enum.LookupEnumValue): If the value is an EnumConstant, - check whether an implicit conversion to the current enum's UnderlyingType - exists and report an error if not. - - * codegen.cs (CodeGen.Init): Delete the symbol file when compiling - without debugging support. - - * delegate.cs (Delegate.CloseDelegate): Removed, use CloseType instead. - Fixes bug #30235. Thanks to Ricardo Fernández Pascual. - -2002-09-12 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.IsNestedChildOf): New method. - - * ecore.cs (IMemberExpr.DeclaringType): New property. - (SimpleName.SimpleNameResolve): Check whether we're accessing a - nonstatic member of an outer type (CS0038). - -2002-09-11 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Activate the using-error detector at warning level - 4 (at least for MS-compatible APIs). - - * namespace.cs (VerifyUsing): Small buglett fix. - - * pending.cs (PendingImplementation): pass the container pointer. - - * interface.cs (GetMethods): Allow for recursive definition. Long - term, I would like to move every type to support recursive - definitions, not the current ordering mechanism that we have right - now. - - The situation is this: Attributes are handled before interfaces, - so we can apply attributes to interfaces. But some attributes - implement interfaces, we will now handle the simple cases - (recursive definitions will just get an error). - - * parameter.cs: Only invalidate types at the end if we fail to - lookup all types. - -2002-09-09 Martin Baulig <martin@gnome.org> - - * ecore.cs (PropertyExpr.Emit): Also check for - TypeManager.system_int_array_get_length so this'll also work when - compiling corlib. Fixes #30003. - -2002-09-09 Martin Baulig <martin@gnome.org> - - * expression.cs (ArrayCreation.MakeByteBlob): Added support for enums - and throw an exception if we can't get the type's size. Fixed #30040, - added test-165.cs. - -2002-09-09 Martin Baulig <martin@gnome.org> - - * ecore.cs (PropertyExpr.DoResolve): Added check for static properies. - - * expression.cs (SizeOf.DoResolve): Sizeof is only allowed in unsafe - context. Fixes bug #30027. - - * delegate.cs (NewDelegate.Emit): Use OpCodes.Ldvirtftn for - virtual functions. Fixes bug #30043, added test-164.cs. - -2002-09-08 Ravi Pratap <ravi@ximian.com> - - * attribute.cs : Fix a small NullRef crash thanks to my stupidity. - -2002-09-08 Nick Drochak <ndrochak@gol.com> - - * driver.cs: Use an object to get the windows codepage since it's not a - static property. - -2002-09-08 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (For.Emit): for infinite loops (test == null) - return whether there is a break inside, not always "true". - - * namespace.cs (UsingEntry): New struct to hold the name of the - using definition, the location where it is defined, and whether it - has been used in a successful type lookup. - - * rootcontext.cs (NamespaceLookup): Use UsingEntries instead of - strings. - - * decl.cs: ditto. - -2002-09-06 Ravi Pratap <ravi@ximian.com> - - * attribute.cs : Fix incorrect code which relied on catching - a NullReferenceException to detect a null being passed in - where an object was expected. - -2002-09-06 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Try): flag the catch variable as assigned - - * expression.cs (Cast): Simplified by using ResolveType instead of - manually resolving. - - * statement.cs (Catch): Fix bug by using ResolveType. - -2002-09-06 Ravi Pratap <ravi@ximian.com> - - * expression.cs (BetterConversion): Special case for when we have - a NullLiteral as the argument and we have to choose between string - and object types - we choose string the way csc does. - - * attribute.cs (Attribute.Resolve): Catch the - NullReferenceException and report error #182 since the Mono - runtime no more has the bug and having this exception raised means - we tried to select a constructor which takes an object and is - passed a null. - -2002-09-05 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation.OverloadResolve): Flag a nicer error - message (1502, 1503) when we can't locate a method after overload - resolution. This is much more informative and closes the bug - Miguel reported. - - * interface.cs (PopulateMethod): Return if there are no argument - types. Fixes a NullReferenceException bug. - - * attribute.cs (Attribute.Resolve): Ensure we allow TypeOf - expressions too. Previously we were checking only in one place for - positional arguments leaving out named arguments. - - * ecore.cs (ImplicitNumericConversion): Conversion from underlying - type to the enum type is not allowed. Remove code corresponding to - that. - - (ConvertNumericExplicit): Allow explicit conversions from - the underlying type to enum type. This precisely follows the spec - and closes a bug filed by Gonzalo. - -2002-09-04 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * compiler.csproj: - * compiler.csproj.user: patch from Adam Chester (achester@bigpond.com). - -2002-09-03 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (SwitchLabel.ResolveAndReduce): In the string case, - it was important that we stored the right value after the - reduction in `converted'. - -2002-09-04 Martin Baulig <martin@gnome.org> - - * location.cs (Location.SymbolDocument): Use full pathnames for the - source files. - -2002-08-30 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ComposedCast): Use DeclSparce.ResolveType instead - of the expression resolve mechanism, because that will catch the - SimpleName error failures. - - (Conditional): If we can not resolve the - expression, return, do not crash. - -2002-08-29 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * cs-tokenizer.cs: - (location): display token name instead of its number. - -2002-08-28 Martin Baulig <martin@gnome.org> - - * expression.cs (Binary.ResolveOperator): Don't silently return - but return an error if an operator cannot be applied between two - enum types. - -2002-08-28 Martin Baulig <martin@gnome.org> - - * class.cs (Constructor.Define): Set the permission attributes - correctly instead of making all constructors public. - -2002-08-28 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.DoResolve): Do a TypeManager.MemberLook - for private members before reporting a CS0103; if we find anything, - it's a CS0122. - -2002-08-28 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.FilterWithClosure): It's not enough - to check whether `closure_start_type == closure_invocation_type', - we also need to check whether `m.DeclaringType == closure_invocation_type' - before bypassing the permission checks. We might be accessing - protected/private members from the base class. - (TypeManager.RealMemberLookup): Only set private_ok if private - members were requested via BindingFlags.NonPublic. - - * ecore.cs (MethodGroupExpr.IsExplicitImpl): New property. - - * expression.cs (MemberAccess.ResolveMemberAccess): Set - MethodGroupExpr.IsExplicitImpl if appropriate. - (Invocation.DoResolve): Don't report the CS0120 for explicit - interface implementations. - -2002-08-27 Martin Baulig <martin@gnome.org> - - * expression.cs (Invocation.DoResolve): If this is a static - method and we don't have an InstanceExpression, we must report - a CS0120. - -2002-08-25 Martin Baulig <martin@gnome.org> - - * expression.cs (Binary.ResolveOperator): Don't allow `!=' and - `==' between a valuetype and an object. - -2002-08-25 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (TypeExpr): Provide a ToString method. - -2002-08-24 Martin Baulig <martin@gnome.org> - - * codegen.cs (CodeGen.InitMonoSymbolWriter): The symbol file is - now called proggie.dbg and it's a binary file. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * decl.cs (MemberCache.AddMethods): Ignore varargs methods. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * struct.cs (MyStructInfo.ctor): Make this work with empty - structs; it's not allowed to use foreach() on null. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * codegen.cs (CodeGen.InitMonoSymbolWriter): Tell the symbol - writer the full pathname of the generated assembly. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * statements.cs (FlowBranching.UsageVector.MergeChildren): - A `finally' block never returns or breaks; improved handling of - unreachable code. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * statement.cs (Throw.Resolve): Allow `throw null'. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * expression.cs (MemberAccess.ResolveMemberAccess): If this is an - EventExpr, don't do a DeclaredOnly MemberLookup, but check whether - `ee.EventInfo.DeclaringType == ec.ContainerType'. The - MemberLookup would return a wrong event if this is an explicit - interface implementation and the class has an event with the same - name. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * statement.cs (Block.AddChildVariableNames): New public method. - (Block.AddChildVariableName): Likewise. - (Block.IsVariableNameUsedInChildBlock): Likewise. - (Block.AddVariable): Check whether a variable name has already - been used in a child block. - - * cs-parser.jay (declare_local_variables): Mark all variable names - from the current block as being used in a child block in the - implicit block. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * codegen.cs (CodeGen.InitializeSymbolWriter): Abort if we can't - find the symbol writer. - - * driver.cs: csc also allows the arguments to /define being - separated by commas, not only by semicolons. - -2002-08-23 Martin Baulig <martin@gnome.org> - - * interface.cs (Interface.GetMembers): Added static check for events. - -2002-08-15 Martin Baulig <martin@gnome.org> - - * class.cs (MethodData.EmitDestructor): In the Expression.MemberLookup - call, use ec.ContainerType.BaseType as queried_type and invocation_type. - - * ecore.cs (Expression.MemberLookup): Added documentation and explained - why the MethodData.EmitDestructor() change was necessary. - -2002-08-20 Martin Baulig <martin@gnome.org> - - * class.cs (TypeContainer.FindMembers): Added static check for events. - - * decl.cs (MemberCache.AddMembers): Handle events like normal members. - - * typemanager.cs (TypeHandle.GetMembers): When queried for events only, - use Type.GetEvents(), not Type.FindMembers(). - -2002-08-20 Martin Baulig <martin@gnome.org> - - * decl.cs (MemberCache): Added a special method cache which will - be used for method-only searched. This ensures that a method - search will return a MethodInfo with the correct ReflectedType for - inherited methods. - -2002-08-20 Martin Baulig <martin@gnome.org> - - * decl.cs (DeclSpace.FindMembers): Made this public. - -2002-08-20 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * delegate.cs: fixed build on windows. - [FIXME: Filed as bug #29150: MCS must report these errors.] - -2002-08-19 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (StandardConversionExists): Return a false - if we are trying to convert the void type to anything else - since that is not allowed. - - * delegate.cs (DelegateInvocation.DoResolve): Ensure that - we flag error 70 in the event an event is trying to be accessed - directly from outside the declaring type. - -2002-08-20 Martin Baulig <martin@gnome.org> - - * typemanager.cs, decl.cs: Moved MemberList, IMemberContainer and - MemberCache from typemanager.cs to decl.cs. - -2002-08-19 Martin Baulig <martin@gnome.org> - - * class.cs (TypeContainer): Implement IMemberContainer. - (TypeContainer.DefineMembers): Create the MemberCache. - (TypeContainer.FindMembers): Do better BindingFlags checking; only - return public members if BindingFlags.Public was given, check - whether members are static. - -2002-08-16 Martin Baulig <martin@gnome.org> - - * decl.cs (DeclSpace.Define): Splitted this in Define and - DefineMembers. DefineMembers is called first and initializes the - MemberCache. - - * rootcontext.cs (RootContext.DefineMembers): New function. Calls - DefineMembers() on all our DeclSpaces. - - * class.cs (TypeContainer.Define): Moved all code to DefineMembers(), - but call DefineMembers() on all nested interfaces. We call their - Define() in our new Define() function. - - * interface.cs (Interface): Implement IMemberContainer. - (Interface.Define): Moved all code except the attribute stuf to - DefineMembers(). - (Interface.DefineMembers): Initialize the member cache. - - * typemanager.cs (IMemberFinder): Removed this interface, we don't - need this anymore since we can use MemberCache.FindMembers directly. - -2002-08-19 Martin Baulig <martin@gnome.org> - - * typemanager.cs (MemberCache): When creating the cache for an - interface type, add all inherited members. - (TypeManager.MemberLookup_FindMembers): Changed `ref bool searching' - to `out bool used_cache' and documented it. - (TypeManager.MemberLookup): If we already used the cache in the first - iteration, we don't need to do the interfaces check. - -2002-08-19 Martin Baulig <martin@gnome.org> - - * decl.cs (DeclSpace.FindMembers): New abstract method. Moved this - here from IMemberFinder and don't implement this interface anymore. - (DeclSpace.MemberCache): Moved here from IMemberFinder. - - * typemanager.cs (IMemberFinder): This interface is now only used by - classes which actually support the member cache. - (TypeManager.builder_to_member_finder): Renamed to builder_to_declspace - since we only put DeclSpaces into this Hashtable. - (MemberLookup_FindMembers): Use `builder_to_declspace' if the type is - a dynamic type and TypeHandle.GetTypeHandle() otherwise. - -2002-08-16 Martin Baulig <martin@gnome.org> - - * typemanager.cs (ICachingMemberFinder): Removed. - (IMemberFinder.MemberCache): New property. - (TypeManager.FindMembers): Merged this with RealFindMembers(). - This function will never be called from TypeManager.MemberLookup() - so we can't use the cache here, just the IMemberFinder. - (TypeManager.MemberLookup_FindMembers): Check whether the - IMemberFinder has a MemberCache and call the cache's FindMembers - function. - (MemberCache): Rewrote larger parts of this yet another time and - cleaned it up a bit. - -2002-08-15 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (LoadArgs): Support quoting. - - (Usage): Show the CSC-like command line arguments. - - Improved a few error messages. - -2002-08-15 Martin Baulig <martin@gnome.org> - - * typemanager.cs (IMemberContainer.Type): New property. - (IMemberContainer.IsInterface): New property. - - The following changes are conditional to BROKEN_RUNTIME, which is - defined at the top of the file. - - * typemanager.cs (MemberCache.MemberCache): Don't add the base - class'es members, but add all members from TypeHandle.ObjectType - if we're an interface. - (MemberCache.AddMembers): Set the Declared flag if member.DeclaringType - is the current type. - (MemberCache.CacheEntry.Container): Removed this field. - (TypeHandle.GetMembers): Include inherited members. - -2002-08-14 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * typemanager.cs: fixed compilation and added a comment on a field that - is never used. - -2002-08-15 Martin Baulig <martin@gnome.org> - - * class.cs (ConstructorInitializer.Resolve): In the - Expression.MemberLookup call, use the queried_type as - invocation_type. - - * typemanager.cs (IMemberContainer.GetMembers): Removed the `bool - declared' attribute, it's always true. - (IMemberContainer.Parent, IMemberContainer.Name): New properties. - (TypeManager.MemberLookup_FindMembers): [FIXME FIXME FIXME] Added - temporary wrapper for FindMembers which tells MemberLookup whether - members from the base classes are included in the return value. - This will go away soon. - (TypeManager.MemberLookup): Use this temporary hack here; once the - new MemberCache is completed, we don't need to do the DeclaredOnly - looping here anymore since the MemberCache will take care of this. - (TypeManager.IsSubclassOrNestedChildOf): Allow `type == parent'. - (MemberCache): When creating the MemberCache for a class, get - members from the current class and all its base classes. - (MemberCache.CacheEntry.Container): New field. This is a - temporary hack until the Mono runtime is fixed to distinguish - between ReflectedType and DeclaringType. It allows us to use MCS - with both the MS runtime and the unfixed Mono runtime without - problems and without accecting performance. - (MemberCache.SearchMembers): The DeclaredOnly looping from - TypeManager.MemberLookup is now done here. - -2002-08-14 Martin Baulig <martin@gnome.org> - - * statement.cs (MyStructInfo.MyStructInfo): Don't call - Type.GetFields on dynamic types but get the fields from the - corresponding TypeContainer. - (MyStructInfo.GetStructInfo): Added check for enum types. - - * typemanager.cs (MemberList.IsSynchronized): Implemented. - (MemberList.SyncRoot): Implemented. - (TypeManager.FilterWithClosure): No need to check permissions if - closure_start_type == closure_invocation_type, don't crash if - closure_invocation_type is null. - -2002-08-13 Martin Baulig <martin@gnome.org> - - Rewrote TypeContainer.FindMembers to use a member cache. This - gives us a speed increase of about 35% for the self-hosting MCS - build and of about 15-20% for the class libs (both on GNU/Linux). - - * report.cs (Timer): New class to get enhanced profiling. This - whole class is "TIMER" conditional since it remarkably slows down - compilation speed. - - * class.cs (MemberList): New class. This is an IList wrapper - which we're now using instead of passing MemberInfo[]'s around to - avoid copying this array unnecessarily. - (IMemberFinder.FindMember): Return a MemberList, not a MemberInfo []. - (ICachingMemberFinder, IMemberContainer): New interface. - (TypeManager.FilterWithClosure): If `criteria' is null, the name - has already been checked, otherwise use it for the name comparision. - (TypeManager.FindMembers): Renamed to RealMemberFinder and - provided wrapper which tries to use ICachingMemberFinder.FindMembers - if possible. Returns a MemberList, not a MemberInfo []. - (TypeHandle): New class, implements IMemberContainer. We create - one instance of this class per type, it contains a MemberCache - which is used to do the member lookups. - (MemberCache): New class. Each instance of this class contains - all members of a type and a name-based hash table. - (MemberCache.FindMembers): This is our new member lookup - function. First, it looks up all members of the requested name in - the hash table. Then, it walks this list and sorts out all - applicable members and returns them. - -2002-08-13 Martin Baulig <martin@gnome.org> - - In addition to a nice code cleanup, this gives us a performance - increase of about 1.4% on GNU/Linux - not much, but it's already - half a second for the self-hosting MCS compilation. - - * typemanager.cs (IMemberFinder): New interface. It is used by - TypeManager.FindMembers to call FindMembers on a TypeContainer, - Enum, Delegate or Interface. - (TypeManager.finder_to_member_finder): New PtrHashtable. - (TypeManager.finder_to_container): Removed. - (TypeManager.finder_to_delegate): Removed. - (TypeManager.finder_to_interface): Removed. - (TypeManager.finder_to_enum): Removed. - - * interface.cs (Interface): Implement IMemberFinder. - - * delegate.cs (Delegate): Implement IMemberFinder. - - * enum.cs (Enum): Implement IMemberFinder. - - * class.cs (TypeContainer): Implement IMemberFinder. - -2002-08-12 Martin Baulig <martin@gnome.org> - - * ecore.cs (TypeExpr.DoResolveType): Mark this as virtual. - -2002-08-12 Martin Baulig <martin@gnome.org> - - * ecore.cs (ITypeExpression): New interface for expressions which - resolve to a type. - (TypeExpression): Renamed to TypeLookupExpression. - (Expression.DoResolve): If we're doing a types-only lookup, the - expression must implement the ITypeExpression interface and we - call DoResolveType() on it. - (SimpleName): Implement the new ITypeExpression interface. - (SimpleName.SimpleNameResolve): Removed the ec.OnlyLookupTypes - hack, the situation that we're only looking up types can't happen - anymore when this method is called. Moved the type lookup code to - DoResolveType() and call it. - (SimpleName.DoResolveType): This ITypeExpression interface method - is now doing the types-only lookup. - (TypeExpr, TypeLookupExpression): Implement ITypeExpression. - (ResolveFlags): Added MaskExprClass. - - * expression.cs (MemberAccess): Implement the ITypeExpression - interface. - (MemberAccess.DoResolve): Added support for a types-only lookup - when we're called via ITypeExpression.DoResolveType(). - (ComposedCast): Implement the ITypeExpression interface. - - * codegen.cs (EmitContext.OnlyLookupTypes): Removed. Call - Expression.Resolve() with ResolveFlags.Type instead. - -2002-08-12 Martin Baulig <martin@gnome.org> - - * interface.cs (Interface.Define): Apply attributes. - - * attribute.cs (Attribute.ApplyAttributes): Added support for - interface attributes. - -2002-08-11 Martin Baulig <martin@gnome.org> - - * statement.cs (Block.Emit): Only check the "this" variable if we - do not always throw an exception. - - * ecore.cs (PropertyExpr.DoResolveLValue): Implemented, check - whether the property has a set accessor. - -2002-08-11 Martin Baulig <martin@gnome.org> - - Added control flow analysis support for structs. - - * ecore.cs (ResolveFlags): Added `DisableFlowAnalysis' to resolve - with control flow analysis turned off. - (IVariable): New interface. - (SimpleName.SimpleNameResolve): If MemberAccess.ResolveMemberAccess - returns an IMemberExpr, call DoResolve/DoResolveLValue on it. - (FieldExpr.DoResolve): Resolve the instance expression with flow - analysis turned off and do the definite assignment check after the - resolving when we know what the expression will resolve to. - - * expression.cs (LocalVariableReference, ParameterReference): - Implement the new IVariable interface, only call the flow analysis - code if ec.DoFlowAnalysis is true. - (This): Added constructor which takes a Block argument. Implement - the new IVariable interface. - (MemberAccess.DoResolve, MemberAccess.DoResolveLValue): Call - DoResolve/DoResolveLValue on the result of ResolveMemberLookup(). - This does the definite assignment checks for struct members. - - * class.cs (Constructor.Emit): If this is a non-static `struct' - constructor which doesn't have any initializer, call - Block.AddThisVariable() to tell the flow analysis code that all - struct elements must be initialized before control returns from - the constructor. - - * statement.cs (MyStructInfo): New public class. - (UsageVector.this [VariableInfo vi]): Added `int field_idx' - argument to this indexer. If non-zero, check an individual struct - member, not the whole struct. - (FlowBranching.CheckOutParameters): Check struct members. - (FlowBranching.IsVariableAssigned, SetVariableAssigned): Added - overloaded versions of these methods which take an additional - `int field_idx' argument to check struct members. - (FlowBranching.IsParameterAssigned, SetParameterAssigned): Added - overloaded versions of these methods which take an additional - `string field_name' argument to check struct member.s - (VariableInfo): Implement the IVariable interface. - (VariableInfo.StructInfo): New public property. Returns the - MyStructInfo instance of the variable if it's a struct or null. - (Block.AddThisVariable): New public method. This is called from - Constructor.Emit() for non-static `struct' constructor which do - not have any initializer. It creates a special variable for the - "this" instance variable which will be checked by the flow - analysis code to ensure that all of the struct's fields are - initialized before control returns from the constructor. - (UsageVector): Added support for struct members. If a - variable/parameter is a struct with N members, we reserve a slot - in the usage vector for each member. A struct is considered fully - initialized if either the struct itself (slot 0) or all its - members are initialized. - -2002-08-08 Martin Baulig <martin@gnome.org> - - * driver.cs (Driver.MainDriver): Only report an error CS5001 - if there were no compilation errors. - - * codegen.cs (EmitContext.EmitContext): Use the DeclSpace's - `UnsafeContext' property to determine whether the parent is in - unsafe context rather than checking the parent's ModFlags: - classes nested in an unsafe class are unsafe as well. - -2002-08-08 Martin Baulig <martin@gnome.org> - - * statement.cs (UsageVector.MergeChildren): Distinguish between - `Breaks' and `Returns' everywhere, don't set `Breaks' anymore if - we return. Added test17() and test18() to test-154.cs. - -2002-08-08 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.FilterWithClosure): If we have - Family access, make sure the invoking type isn't a subclass of the - queried type (that'd be a CS1540). - - * ecore.cs (Expression.MemberLookup): Added overloaded version of - this method which takes an additional `Type invocation_type'. - - * expression.cs (BaseAccess.DoResolve): Use the base type as - invocation and query type. - (MemberAccess.DoResolve): If the lookup failed and we're about to - report a CS0122, try a lookup with the ec.ContainerType - if this - succeeds, we must report a CS1540. - -2002-08-08 Martin Baulig <martin@gnome.org> - - * ecore.cs (IMemberExpr): Added `bool IsInstance' property. - (MethodGroupExpr): Implement the IMemberExpr interface. - - * expression (MemberAccess.ResolveMemberAccess): No need to have - any special code for MethodGroupExprs anymore, they're now - IMemberExprs. - -2002-08-08 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.FilterWithClosure): Check Assembly, - Family, FamANDAssem and FamORAssem permissions. - (TypeManager.IsSubclassOrNestedChildOf): New public method. - -2002-08-08 Martin Baulig <martin@gnome.org> - - * statement.cs (FlowBranchingType): Added LOOP_BLOCK. - (UsageVector.MergeChildren): `break' breaks unless we're in a switch - or loop block. - -Thu Aug 8 10:28:07 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * driver.cs: implemented /resource option to embed managed resources. - -2002-08-07 Martin Baulig <martin@gnome.org> - - * class.cs (FieldBase.Initializer): Renamed to `init' and made private. - (FieldBase.HasFieldInitializer): New public property. - (FieldBase.GetInitializerExpression): New public method. Resolves and - returns the field initializer and makes sure it is only resolved once. - (TypeContainer.EmitFieldInitializers): Call - FieldBase.GetInitializerExpression to get the initializer, this ensures - that it isn't resolved multiple times. - - * codegen.cs (EmitContext): Added `bool IsFieldInitialier'. This tells - the resolving process (SimpleName/MemberLookup) that we're currently - emitting a field initializer (which must not access any instance members, - this is an error CS0236). - - * ecore.cs (SimpleName.Error_ObjectRefRequired): Added EmitContext - argument, if the `IsFieldInitializer' flag is set, we must report and - error CS0236 and not an error CS0120. - -2002-08-07 Martin Baulig <martin@gnome.org> - - * ecore.cs (IMemberExpr): New public interface. - (FieldExpr, PropertyExpr, EventExpr): Implement IMemberExpr. - (SimpleName.SimpleNameResolve): Call MemberAccess.ResolveMemberAccess - if the expression is an IMemberExpr. - - * expression.cs (MemberAccess.ResolveMemberAccess): Allow `left' - to be null, implicitly default to `this' if we're non-static in - this case. Simplified the code a lot by using the new IMemberExpr - interface. Also fixed bug #28176 here. - -2002-08-06 Martin Baulig <martin@gnome.org> - - * cs-parser.jay (SimpleLookup): Removed. We need to create - ParameterReferences during semantic analysis so that we can do a - type-only search when resolving Cast, TypeOf and SizeOf. - (block): Pass the `current_local_parameters' to the Block's - constructor. - - * class.cs (ConstructorInitializer): Added `Parameters parameters' - argument to the constructor. - (ConstructorInitializer.Resolve): Create a temporary implicit - block with the parameters. - - * ecore.cs (SimpleName.SimpleNameResolve): Resolve parameter - references here if we aren't doing a type-only search. - - * statement.cs (Block): Added constructor which takes a - `Parameters parameters' argument. - (Block.Parameters): New public property. - - * support.cs (InternalParameters.Parameters): Renamed `parameters' - to `Parameters' and made it public readonly. - -2002-08-06 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.Warning): Made this public as well. - - * report.cs (Report.Debug): Print the contents of collections. - -2002-08-06 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.ResolveFlags): New [Flags] enum. This is - used to tell Resolve() which kinds of expressions it may return. - (Expression.Resolve): Added overloaded version of this method which - takes a `ResolveFlags flags' argument. This can be used to tell - Resolve() which kinds of expressions it may return. Reports a - CS0118 on error. - (Expression.ResolveWithSimpleName): Removed, use Resolve() with - ResolveFlags.SimpleName. - (Expression.Error118): Added overloaded version of this method which - takes a `ResolveFlags flags' argument. It uses the flags to determine - which kinds of expressions are allowed. - - * expression.cs (Argument.ResolveMethodGroup): New public method. - Resolves an argument, but allows a MethodGroup to be returned. - This is used when invoking a delegate. - - * TODO: Updated a bit. - -2002-08-06 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - Fixed compilation with csc. - - * ecore.cs: Expression.Error made public. Is this correct? Should - Warning be made public too? - - * expression.cs: use ea.Location instead of ea.loc. - [FIXME: Filed as bug #28607: MCS must report these errors.] - -2002-08-06 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.loc): Moved the location here instead of - duplicating it in all derived classes. - (Expression.Location): New public property. - (Expression.Error, Expression.Warning): Made them non-static and - removed the location argument. - (Expression.Warning): Added overloaded version which takes an - `int level' argument. - (Expression.Error118): Make this non-static and removed the - expression and location arguments. - (TypeExpr): Added location argument to the constructor. - - * expression.cs (StaticCallExpr): Added location argument to - the constructor. - (Indirection, PointerArithmetic): Likewise. - (CheckedExpr, UnCheckedExpr): Likewise. - (ArrayAccess, IndexerAccess, UserCast, ArrayPtr): Likewise. - (StringPtr): Likewise. - - -2002-08-05 Martin Baulig <martin@gnome.org> - - * expression.cs (BaseAccess.DoResolve): Actually report errors. - - * assign.cs (Assign.DoResolve): Check whether the source - expression is a value or variable. - - * statement.cs (Try.Resolve): Set ec.InTry/InCatch/InFinally - while resolving the corresponding blocks. - - * interface.cs (Interface.GetInterfaceTypeByName): Actually report - an error, don't silently return null. - - * statement.cs (Block.AddVariable): Do the error reporting here - and distinguish between CS0128 and CS0136. - (Block.DoResolve): Report all unused labels (warning CS0164). - (LabeledStatement): Pass the location to the constructor. - (LabeledStatement.HasBeenReferenced): New property. - (LabeledStatement.Resolve): Set it to true here. - - * statement.cs (Return.Emit): Return success even after reporting - a type mismatch error (CS0126 or CS0127), this is what csc does and - it avoids confusing the users with any consecutive errors. - -2002-08-05 Martin Baulig <martin@gnome.org> - - * enum.cs (Enum.LookupEnumValue): Catch circular definitions. - - * const.cs (Const.LookupConstantValue): Catch circular definitions. - - * expression.cs (MemberAccess.DoResolve): Silently return if an - error has already been reported. - - * ecore.cs (Expression.MemberLookupFinal): Silently return if an - error has already been reported. - -2002-08-05 Martin Baulig <martin@gnome.org> - - * statement.cs (UsageVector): Only initialize the `parameters' - vector if we actually have any "out" parameters. - -2002-08-05 Martin Baulig <martin@gnome.org> - - * expression.cs (Binary.ResolveOperator): When combining delegates, - they must have the same type. - -2002-08-05 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.GetArgumentTypes): Don't call - PropertyInfo.GetIndexParameters() on dynamic types, this doesn't - work with the ms runtime and we also don't need it: if we're a - PropertyBuilder and not in the `indexer_arguments' hash, then we - are a property and not an indexer. - - * class.cs (TypeContainer.AsAccessible): Use Type.IsArray, - Type.IsPointer and Type.IsByRef instead of Type.HasElementType - since the latter one doesn't work with the ms runtime. - -2002-08-03 Martin Baulig <martin@gnome.org> - - Fixed bugs #27998 and #22735. - - * class.cs (Method.IsOperator): New public field. - (Method.CheckBase): Report CS0111 if there's already a method - with the same parameters in the current class. Report CS0508 when - attempting to change the return type of an inherited method. - (MethodData.Emit): Report CS0179 if a method doesn't have a body - and it's not marked abstract or extern. - (PropertyBase): New abstract base class for Property and Indexer. - (PropertyBase.CheckBase): Moved here from Property and made it work - for indexers. - (PropertyBase.Emit): Moved here from Property.Emit, Indexer.Emit is - the same so we can reuse it there. - (Property, Indexer): Derive from PropertyBase. - (MethodSignature.inheritable_property_signature_filter): New delegate - to find properties and indexers. - - * decl.cs (MemberCore.CheckMethodAgainstBase): Added `string name' - argument and improved error reporting. - - * parameter.cs (Parameters.GetEmptyReadOnlyParameters): Renamed to - EmptyReadOnlyParameters and made it a property. - - * typemanager.cs (TypeManager.GetArgumentTypes): Added overloaded - version of this method which takes a `PropertyInfo indexer'. - (TypeManager.RegisterIndexer): New method. - - * class.cs: Added myself as author of this file :-) - -2002-08-03 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * class.cs: fixed compilation on windoze. - -2002-08-03 Martin Baulig <martin@gnome.org> - - * interface.cs (Interface.GetInterfaceBases): Check whether all - base interfaces are at least as accessible than the current one. - - * class.cs (TypeContainer.GetClassBases): Check whether base types - are at least as accessible than the current type. - (TypeContainer.AsAccessible): Implemented and made non-static. - (MemberBase.CheckParameters): Report errors if the accessibility - checks fail. - - * delegate.cs (Delegate.Delegate): The default visibility is - internal for top-level types and private for nested types. - (Delegate.Define): Report errors if the accessibility checks fail. - - * enum.cs (Enum.Enum): The default visibility is internal for - top-level types and private for nested types. - (Enum.DefineType): Compute the correct visibility. - - * modifiers.cs (Modifiers.TypeAttr): Added a version of this - function which takes a `bool is_toplevel' instead of a TypeContainer. - - * typemanager.cs (TypeManager.IsBuiltinType): `void' is also a - builtin type. - -2002-08-02 Martin Baulig <martin@gnome.org> - - * expression.cs (LocalVariableReferenc): Added constructor which - takes additional `VariableInfo vi' and `bool is_readonly' arguments. - (LocalVariableReference.IsReadOnly): New property. - (LocalVariableReference.DoResolveLValue): Report a CS1604 if the - variable is readonly, use our own readonly flag to do this; you can - use the new constructor to get a writable reference to a read-only - variable. - - * cs-parser.jay (foreach_statement, using_statement): Get a writable - reference to the local variable. - -2002-08-01 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs (ResolveCore): Also include System.Exception - - * statement.cs (Block.Emit): Do not emit the dead-code warnings if - we reach an EmptyStatement. - - (Catch.DoResolve, Throw.DoResolve): Throwing the System.Exception - is also fine. - - * expression.cs (Binary.ResolveOperator): Check error result in - two places. - - use brtrue/brfalse directly and avoid compares to null. - -2002-08-02 Martin Baulig <martin@gnome.org> - - * class.cs (TypeContainer.Define): Define all nested interfaces here. - Fixes bug #28407, added test-155.cs. - -2002-08-01 Martin Baulig <martin@gnome.org> - - * class.cs (Event.EmitDefaultMethod): Make this work with static - events. Fixes #28311, added verify-3.cs. - -2002-08-01 Martin Baulig <martin@gnome.org> - - * statement.cs (ForeachHelperMethods): Added `enumerator_type' and - `is_disposable' fields. - (Foreach.GetEnumeratorFilter): Set `hm.enumerator_type' and - `hm.is_disposable' if we're using the collection pattern. - (Foreach.EmitCollectionForeach): Use the correct type for the - enumerator's local variable, only emit the try/finally block if - necessary (fixes #27713). - -2002-08-01 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.report118): Renamed to Error118 and made - it public static. - - * statement.cs (Throw.Resolve): Check whether the expression is of - the correct type (CS0118) and whether the type derives from - System.Exception (CS0155). - (Catch.Resolve): New method. Do the type lookup here and check - whether it derives from System.Exception (CS0155). - (Catch.CatchType, Catch.IsGeneral): New public properties. - - * typemanager.cs (TypeManager.exception_type): Added. - -2002-07-31 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Updated About function. - -2002-07-31 Martin Baulig <martin@gnome.org> - - Implemented Control Flow Analysis. - - * codegen.cs (EmitContext.DoFlowAnalysis): New public variable. - (EmitContext.CurrentBranching): Added. - (EmitContext.StartFlowBranching): Added. - (EmitContext.EndFlowBranching): Added. - (EmitContext.KillFlowBranching): Added. - (EmitContext.IsVariableAssigned): Added. - (EmitContext.SetVariableAssigned): Added. - (EmitContext.IsParameterAssigned): Added. - (EmitContext.SetParameterAssigned): Added. - (EmitContext.EmitTopBlock): Added `InternalParameters ip' argument. - Added control flow analysis stuff here. - - * expression.cs (Unary.DoResolve): If the operator is Oper.AddressOf, - resolve the expression as lvalue. - (LocalVariableReference.DoResolve): Check whether the variable has - already been assigned. - (ParameterReference.DoResolveLValue): Override lvalue resolve to mark - the parameter as assigned here. - (ParameterReference.DoResolve): Check whether the parameter has already - been assigned. - (Argument.Resolve): If it's a `ref' or `out' argument, resolve the - expression as lvalue. - - * statement.cs (FlowBranching): New class for the flow analysis code. - (Goto): Resolve the label in Resolve, not in Emit; added flow analysis. - (LabeledStatement.IsDefined): New public property. - (LabeledStatement.AddUsageVector): New public method to tell flow - analyis that the label may be reached via a forward jump. - (GotoCase): Lookup and resolve the label in Resolve, not in Emit; added - flow analysis. - (VariableInfo.Number): New public field. This is used by flow analysis - to number all locals of a block. - (Block.CountVariables): New public property. This is the number of - local variables in this block (including the locals from all parent - blocks). - (Block.EmitMeta): Number all the variables. - - * statement.cs: Added flow analysis support to all classes. - -2002-07-31 Martin Baulig <martin@gnome.org> - - * driver.cs: Added "--mcs-debug" argument if MCS_DEBUG is defined. - To get debugging messages, compile mcs with /define:MCS_DEBUG and - then use this argument. - - * report.cs (Report.Debug): Renamed to conditional to "MCS_DEBUG". - - * makefile.gnu (MCS_FLAGS): Include $(MCS_DEFINES), the user may - use this to specify /define options. - -2002-07-29 Martin Baulig <martin@gnome.org> - - * statement.cs (Fixed): Moved all code that does variable lookups - and resolvings from Emit to Resolve. - - * statement.cs (For): Moved all code that does variable lookups - and resolvings from Emit to Resolve. - - * statement.cs (Using): Moved all code that does variable lookups - and resolvings from Emit to Resolve. - -2002-07-29 Martin Baulig <martin@gnome.org> - - * attribute.cs (Attribute.Resolve): Explicitly catch a - System.NullReferenceException when creating the - CustromAttributeBuilder and report a different warning message. - -2002-07-29 Martin Baulig <martin@gnome.org> - - * support.cs (ParameterData.ParameterName): Added method to - get the name of a parameter. - - * typemanager.cs (TypeManager.IsValueType): New public method. - -2002-07-29 Martin Baulig <martin@gnome.org> - - * parameter.cs (Parameter.Modifier): Added `ISBYREF = 8'. This - is a flag which specifies that it's either ref or out. - (Parameter.GetParameterInfo (DeclSpace, int, out bool)): Changed - the out parameter to `out Parameter.Modifier mod', also set the - Parameter.Modifier.ISBYREF flag on it if it's either ref or out. - - * support.cs (InternalParameters.ParameterModifier): Distinguish - between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the - Parameter.Modifier.ISBYREF flag if it's either ref or out. - - * expression.cs (Argument.GetParameterModifier): Distinguish - between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the - Parameter.Modifier.ISBYREF flag if it's either ref or out. - -2002-07-29 Martin Baulig <martin@gnome.org> - - * expression.cs (ParameterReference.ParameterReference): Added - `Location loc' argument to the constructor. - - * cs-parser.jay: Pass location to ParameterReference. - -2002-07-28 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Try): Initialize the location. - - * cs-parser.jay: pass location to Try. - - * expression.cs (Unary.Reduce): Change the prototype to return - whether a constant fold could be performed or not. The result is - returned in an out parameters. In the case of Indirection and - AddressOf, we want to perform the full tests. - -2002-07-26 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Statement.Emit): Flag dead code. - -2002-07-27 Andrew Birkett <andy@nobugs.org> - - * expression.cs (Unary.Reduce): Handle AddressOf and Indirection. - -2002-07-27 Martin Baulig <martin@gnome.org> - - * class.cs (MethodData.Define): Put back call to - TypeManager.AddMethod(), accidentally commented this out. - - * report.cs (Debug): New public method to print debugging information, - this is `[Conditional ("DEBUG")]'. - -2002-07-26 Martin Baulig <martin@gnome.org> - - * cs-parser.jay (CSharpParser): Added `Stack switch_stack'. - (switch_statement): Push the current_block to the switch_stack and - pop it again when we're done with the switch. - (switch_section): The new block is a child of the current_block. - Fixes bug #24007, added test-152.cs. - -2002-07-27 Martin Baulig <martin@gnome.org> - - * expression.cs (Invocation.EmitArguments): When calling a varargs - function with only its fixed arguments, we need to pass an empty - array. - -2002-07-27 Martin Baulig <martin@gnome.org> - - Mono 0.13 has been released. - -2002-07-25 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Rename --resource to --linkres, because that is what - we do currently, we dont support --resource yet. - - * cs-tokenizer.cs: Fix test for reporting endif mismatches. - -2002-07-25 Martin Baulig <martin@gnome.org> - - * class.cs (MethodData): New public class. This is a `method builder' - class for a method or one accessor of a Property/Indexer/Event. - (MethodData.GetMethodFlags): Moved here from MemberBase. - (MethodData.ApplyAttributes): Likewise. - (MethodData.ApplyObsoleteAttribute): Likewise. - (MethodData.ApplyConditionalAttribute): Likewise. - (MethodData.ApplyDllImportAttribute): Likewise. - (MethodData.CheckAbstractAndExternal): Likewise. - (MethodData.Define): Formerly knows as MemberBase.DefineMethod(). - (MethodData.Emit): Formerly known as Method.Emit(). - (MemberBase): Moved everything which was specific to a single - accessor/method to MethodData. - (Method): Create a new MethodData and call Define() and Emit() on it. - (Property, Indexer, Event): Create a new MethodData objects for each - accessor and call Define() and Emit() on them. - -2002-07-25 Martin Baulig <martin@gnome.org> - - Made MethodCore derive from MemberBase to reuse the code from there. - MemberBase now also checks for attributes. - - * class.cs (MethodCore): Derive from MemberBase, not MemberCore. - (MemberBase.GetMethodFlags): Moved here from class Method and marked - as virtual. - (MemberBase.DefineAccessor): Renamed to DefineMethod(), added - `CallingConventions cc' and `Attributes opt_attrs' arguments. - (MemberBase.ApplyAttributes): New virtual method; applies the - attributes to a method or accessor. - (MemberBase.ApplyObsoleteAttribute): New protected virtual method. - (MemberBase.ApplyConditionalAttribute): Likewise. - (MemberBase.ApplyDllImportAttribute): Likewise. - (MemberBase.CheckAbstractAndExternal): Likewise. - (MethodCore.ParameterTypes): This is now a property instead of a - method, it's initialized from DoDefineParameters(). - (MethodCore.ParameterInfo): Removed the set accessor. - (MethodCore.DoDefineParameters): New protected virtual method to - initialize ParameterTypes and ParameterInfo. - (Method.GetReturnType): We can now simply return the MemberType. - (Method.GetMethodFlags): Override the MemberBase version and add - the conditional flags. - (Method.CheckBase): Moved some code from Define() here, call - DoDefineParameters() here. - (Method.Define): Use DoDefine() and DefineMethod() from MemberBase - here to avoid some larger code duplication. - (Property.Emit, Indexer.Emit): Call CheckAbstractAndExternal() to - ensure that abstract and external accessors don't declare a body. - - * attribute.cs (Attribute.GetValidPieces): Make this actually work: - `System.Attribute.GetCustomAttributes (attr.Type)' does a recursive - lookup in the attribute's parent classes, so we need to abort as soon - as we found the first match. - (Attribute.Obsolete_GetObsoleteMessage): Return the empty string if - the attribute has no arguments. - - * typemanager.cs (TypeManager.AddMethod): Now takes a MemberBase instead - of a Method. - -2002-07-24 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * cs-parser.jay: reverted previous patch. - -2002-07-24 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * cs-parser.jay: fixed bug #22119. - -2002-07-24 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * attribute.cs: fixed compilation. The error was: - "attribute.cs(571,17): error CS0177: The out parameter 'is_error' must - be assigned to before control leaves the current method." - [FIXME: Filed as bug #28186: MCS must report this error.] - -2002-07-25 Martin Baulig <martin@gnome.org> - - * attribute.cs (Attribute.Conditional_GetConditionName): New static - method to pull the condition name ouf of a Conditional attribute. - (Attribute.Obsolete_GetObsoleteMessage): New static method to pull - the obsolete message and error flag out of an Obsolete attribute. - - * class.cs (Method.GetMethodFlags): New public method to get the - TypeManager.MethodFlags for this method. - (Method.ApplyConditionalAttribute, Method.ApplyObsoleteAttribute): New - private methods. - (Method.Define): Get and apply the Obsolete and Conditional attributes; - if we're overriding a virtual function, set the new private variable - `parent_method'; call the new TypeManager.AddMethod(). - - * typemanager.cs (TypeManager.AddMethod): New static method. Stores - the MethodBuilder and the Method in a PtrHashtable. - (TypeManager.builder_to_method): Added for this purpose. - (TypeManager.MethodFlags): Added IsObsoleteError. - (TypeManager.GetMethodFlags): Added `Location loc' argument. Lookup - Obsolete and Conditional arguments in MethodBuilders. If we discover - an Obsolete attribute, emit an appropriate warning 618 / error 619 with - the message from the attribute. - -2002-07-24 Martin Baulig <martin@gnome.org> - - * cs-tokenizer.cs: Eat up trailing whitespaces and one-line comments in - preprocessor directives, ensure that the argument to #define/#undef is - exactly one identifier and that it's actually an identifier. - - Some weeks ago I did a `#define DEBUG 1' myself and wondered why this - did not work .... - -2002-07-24 Martin Baulig <martin@gnome.org> - - * statement.cs (Foreach.ForeachHelperMethods): Added `Type element_type', - initialize it to TypeManager.object_type in the constructor. - (Foreach.GetEnumeratorFilter): Set `hm.element_type' to the return type - of the `hm.get_current' method if we're using the collection pattern. - (Foreach.EmitCollectionForeach): Use `hm.element_type' as the source type - for the explicit conversion to make it work when we're using the collection - pattern and the `Current' property has a different return type than `object'. - Fixes #27713. - -2002-07-24 Martin Baulig <martin@gnome.org> - - * delegate.cs (Delegate.VerifyMethod): Simply return null if the method - does not match, but don't report any errors. This method is called in - order for all methods in a MethodGroupExpr until a matching method is - found, so we don't want to bail out if the first method doesn't match. - (NewDelegate.DoResolve): If none of the methods in the MethodGroupExpr - matches, report the 123. Fixes #28070. - -2002-07-24 Martin Baulig <martin@gnome.org> - - * expression.cs (ArrayAccess.EmitStoreOpcode): Moved the - TypeManager.TypeToCoreType() to the top of the method so the - following equality checks will work. Fixes #28107. - -2002-07-24 Martin Baulig <martin@gnome.org> - - * cfold.cs (ConstantFold.DoConstantNumericPromotions): "If either - operand is of type uint, and the other operand is of type sbyte, - short or int, the operands are converted to type long." - - Actually do what this comment already told us. Fixes bug #28106, - added test-150.cs. - -2002-07-24 Martin Baulig <martin@gnome.org> - - * class.cs (MethodBase): New abstract class. This is now a base - class for Property, Indexer and Event to avoid some code duplication - in their Define() and DefineMethods() methods. - (MethodBase.DoDefine, MethodBase.DefineAccessor): Provide virtual - generic methods for Define() and DefineMethods(). - (FieldBase): Derive from MemberBase, not MemberCore. - (Property): Derive from MemberBase, not MemberCore. - (Property.DefineMethod): Moved all the code from this method to the - new MethodBase.DefineAccessor(), just call it with appropriate - argumetnts. - (Property.Define): Call the new Property.DoDefine(), this does some - sanity checks and we don't need to duplicate the code everywhere. - (Event): Derive from MemberBase, not MemberCore. - (Event.Define): Use the new MethodBase.DefineAccessor() to define the - accessors, this will also make them work with interface events. - (Indexer): Derive from MemberBase, not MemberCore. - (Indexer.DefineMethod): Removed, call MethodBase.DefineAccessor() insstead. - (Indexer.Define): Use the new MethodBase functions. - - * interface.cs (InterfaceEvent.InterfaceEvent): Added `Location loc' - argument to the constructor. - (Interface.FindMembers): Added support for interface events. - (Interface.PopluateEvent): Implemented. - - Added test-149.cs for this. This also fixes bugs #26067 and #24256. - -2002-07-22 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer.AddMethod): Adding methods do not use IsValid, - but this is required to check for a method name being the same as - the containing class. - - Handle this now. - -2002-07-22 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * interface.cs: initialize variable. - -2002-07-23 Martin Baulig <martin@gnome.org> - - Implemented the IndexerName attribute in interfaces. - - * class.cs (TypeContainer.DefineIndexers): Don't set the indexer - name if this is an explicit interface implementation. - (Indexer.InterfaceIndexerName): New public variable. If we're - implementing an interface indexer, this is the IndexerName in that - interface. Otherwise, it's the IndexerName. - (Indexer.DefineMethod): If we're implementing interface indexer, - set InterfaceIndexerName. Use the new Pending.IsInterfaceIndexer - and Pending.ImplementIndexer methods. - (Indexer.Define): Also define the PropertyBuilder if we're - implementing an interface indexer and this is neither an explicit - interface implementation nor do the IndexerName match the one in - the interface. - - * pending.cs (TypeAndMethods): Added `MethodInfo [] need_proxy'. - If a method is defined here, then we always need to create a proxy - for it. This is used when implementing interface indexers. - (Pending.IsInterfaceIndexer): New public method. - (Pending.ImplementIndexer): New public method. - (Pending.InterfaceMethod): Added `MethodInfo need_proxy' argument. - This is used when implementing interface indexers to define a proxy - if necessary. - (Pending.VerifyPendingMethods): Look in the `need_proxy' array and - define a proxy if necessary. - - * interface.cs (Interface.IndexerName): New public variable. - (Interface.PopulateIndexer): Set the IndexerName. - (Interface.DefineIndexers): New private method. Populate all the - indexers and make sure their IndexerNames match. - - * typemanager.cs (IndexerPropertyName): Added support for interface - indexers. - -2002-07-22 Martin Baulig <martin@gnome.org> - - * codegen.cs (EmitContext.HasReturnLabel): New public variable. - (EmitContext.EmitTopBlock): Always mark the ReturnLabel and emit a - ret if HasReturnLabel. - (EmitContext.TryCatchLevel, LoopBeginTryCatchLevel): New public - variables. - - * statement.cs (Do.Emit, While.Emit, For.Emit, Foreach.Emit): Save - and set the ec.LoopBeginTryCatchLevel. - (Try.Emit): Increment the ec.TryCatchLevel while emitting the block. - (Continue.Emit): If the ec.LoopBeginTryCatchLevel is smaller than - the current ec.TryCatchLevel, the branch goes out of an exception - block. In this case, we need to use Leave and not Br. - -2002-07-22 Martin Baulig <martin@gnome.org> - - * statement.cs (Try.Emit): Emit an explicit ret after the end of the - block unless the block does not always return or it is contained in - another try { ... } catch { ... } block. Fixes bug #26506. - Added verify-1.cs to the test suite. - -2002-07-22 Martin Baulig <martin@gnome.org> - - * statement.cs (Switch.TableSwitchEmit): If we don't have a default, - then we do not always return. Fixes bug #24985. - -2002-07-22 Martin Baulig <martin@gnome.org> - - * expression.cs (Invocation.OverloadedResolve): Do the BetterFunction() - lookup on a per-class level; ie. walk up the class hierarchy until we - found at least one applicable method, then choose the best among them. - Fixes bug #24463 and test-29.cs. - -2002-07-22 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.ArrayContainsMethod): Don't check the - return types of the methods. The return type is not part of the - signature and we must not check it to make the `new' modifier work. - Fixes bug #27999, also added test-147.cs. - (TypeManager.TypeToCoreType): Added TypeManager.type_type. - - * expression.cs (Invocation.DoResolve): Call TypeManager.TypeToCoreType() - on the method's return type. - -2002-07-21 Martin Baulig <martin@gnome.org> - - * assign.cs: Make this work if the rightmost source is a constant and - we need to do an implicit type conversion. Also adding a few more tests - to test-38.cs which should have caught this. - - * makefile.gnu: Disable debugging, there's already the mcs-mono2.exe - target in the makefile for this. The makefile.gnu is primarily intended - for end-users who don't want to debug the compiler. - -2002-07-21 Martin Baulig <martin@gnome.org> - - * assign.cs: Improved the Assign class so it can now handle embedded - assignments (X = Y = Z = something). As a side-effect this'll now also - consume less local variables. test-38.cs now passes with MCS, added - a few new test cases to that test. - -2002-07-20 Martin Baulig <martin@gnome.org> - - * expression.cs (Binary.EmitBranchable): Emit correct unsigned branch - instructions. Fixes bug #27977, also added test-146.cs. - -2002-07-19 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * cs-tokenizer.cs: fixed getHex (). - -2002-07-19 Martin Baulig <martin@gnome.org> - - * expression.cs (Invocation.EmitParams): Use TypeManager.LookupType(), - not Type.GetType() to lookup the array type. This is needed when - we're constructing an array of a user-defined type. - (ArrayAccess.EmitDynamicInitializers): Only emit the Ldelema for - single-dimensional arrays, but also for single-dimensial arrays of - type decimal. - -2002-07-19 Martin Baulig <martin@gnome.org> - - * expression.cs (New.DoEmit): Create a new LocalTemporary each time - this function is called, it's not allowed to share LocalBuilders - among ILGenerators. - -2002-07-19 Martin Baulig <martin@gnome.org> - - * expression.cs (Argument.Resolve): Report an error 118 when trying - to pass a type as argument. - -2002-07-18 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.ImplicitNumericConversion): Don't emit a - Conv_R_Un for the signed `long' type. - -2002-07-15 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (MemberAccess.DoResolve): Do not reuse the field - `expr' for the temporary result, as that will fail if we do - multiple resolves on the same expression. - -2002-07-05 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (SimpleNameResolve): Use ec.DeclSpace instead of - ec.TypeContainer for looking up aliases. - - * class.cs (TypeContainer): Remove LookupAlias from here. - - * decl.cs (DeclSpace); Move here. - -2002-07-01 Miguel de Icaza <miguel@ximian.com> - - * class.cs (FindMembers): Only call filter if the constructor - bulider is not null. - - Also handle delegates in `NestedTypes' now. Now we will perform - type lookups using the standard resolution process. This also - fixes a bug. - - * decl.cs (DeclSpace.ResolveType): New type resolution routine. - This uses Expressions (the limited kind that can be parsed by the - tree) instead of strings. - - * expression.cs (ComposedCast.ToString): Implement, used to flag - errors since now we have to render expressions. - - (ArrayCreation): Kill FormElementType. Use ComposedCasts in - FormArrayType. - - * ecore.cs (SimpleName.ToString): ditto. - - * cs-parser.jay: Instead of using strings to assemble types, use - Expressions to assemble the type (using SimpleName, ComposedCast, - MemberAccess). This should fix the type lookups in declarations, - because we were using a different code path for this. - - * statement.cs (Block.Resolve): Continue processing statements - even when there is an error. - -2002-07-17 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Event.Define): Also remove the `remove' method from - the list of pending items. - - * expression.cs (ParameterReference): Use ldarg.N (0..3) to - generate more compact code. - -2002-07-17 Martin Baulig <martin@gnome.org> - - * const.cs (Const.LookupConstantValue): Add support for constant - `unchecked' and `checked' expressions. - Also adding test case test-140.cs for this. - -2002-07-17 Martin Baulig <martin@gnome.org> - - * statement.cs (Foreach.GetEnumeratorFilter): When compiling corlib, - check whether mi.ReturnType implements the IEnumerator interface; the - `==' and the IsAssignableFrom() will fail in this situation. - -2002-07-16 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (SimpleName.SimpleNameResolve) : Apply Gonzalo's fix - here too. - -2002-07-16 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * expression.cs: fixed bug #27811. - -2002-07-14 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ParameterReference.AddressOf): Patch from Paolo - Molaro: when we are a ref, the value already contains a pointer - value, do not take the address of it. - -2002-07-14 Rafael Teixeira <rafaelteixeirabr@hotmail.com> - * removed mb-parser.jay and mb-tokenizer.cs - -Sat Jul 13 19:38:03 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * expression.cs: check against the building corlib void type. - -Sat Jul 13 19:35:58 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * ecore.cs: fix for valuetype static readonly fields: when - initializing them, we need their address, not the address of a copy. - -Sat Jul 13 17:32:53 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * typemanager.cs: register also enum_type in corlib. - -Sat Jul 13 15:59:47 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * class.cs: allow calling this (but not base) initializers in structs. - -Sat Jul 13 15:12:06 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * ecore.cs: make sure we compare against the building base types - in GetTypeSize (). - -Sat Jul 13 15:10:32 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * typemanager.cs: fix TypeToCoreType() to handle void and object - (corlib gets no more typerefs after this change). - -2002-07-12 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ArrayCreation.EmitArrayArguments): use - Conv.Ovf.U4 for unsigned and Conv.Ovf.I4 for signed. - - (ArrayAccess.LoadArrayAndArguments): Use Conv_Ovf_I and - Conv_Ovf_I_Un for the array arguments. Even if C# allows longs as - array indexes, the runtime actually forbids them. - - * ecore.cs (ExpressionToArrayArgument): Move the conversion code - for array arguments here. - - * expression.cs (EmitLoadOpcode): System.Char is a U2, use that - instead of the default for ValueTypes. - - (New.DoEmit): Use IsValueType instead of - IsSubclassOf (value_type) - (New.DoResolve): ditto. - (Invocation.EmitCall): ditto. - - * assign.cs (Assign): ditto. - - * statement.cs (Unsafe): Ok, so I got the semantics wrong. - Statements *are* currently doing part of their resolution during - Emit. - - Expressions do always resolve during resolve, but statements are - only required to propagate resolution to their children. - -2002-07-11 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (CSCParseOption): Finish the /r: and /lib: support. - - (LoadAssembly): Do not add the dll if it is already specified - - (MainDriver): Add the System directory to the link path at the end, - after all the other -L arguments. - - * expression.cs (ArrayAccess.EmitLoadOpcode): I was using the - wrong opcode for loading bytes and bools (ldelem.i1 instead of - ldelem.u1) and using the opposite for sbytes. - - This fixes Digger, and we can finally run it. - - * driver.cs (UnixParseOption): Move the option parsing here. - (CSCParseOption): Implement CSC-like parsing of options. - - We now support both modes of operation, the old Unix way, and the - new CSC-like way. This should help those who wanted to make cross - platform makefiles. - - The only thing broken is that /r:, /reference: and /lib: are not - implemented, because I want to make those have the same semantics - as the CSC compiler has, and kill once and for all the confussion - around this. Will be doing this tomorrow. - - * statement.cs (Unsafe.Resolve): The state is checked during - resolve, not emit, so we have to set the flags for IsUnsfe here. - -2002-07-10 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (MemberAccess.ResolveMemberAccess): Since we can - not catch the Error_ObjectRefRequired in SimpleName (as it is - possible to have a class/instance variable name that later gets - deambiguated), we have to check this here. - -2002-07-10 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer.GetFieldFromEvent): Move away from here, - make static and put into Expression. - - (Event.Define): Register the private field of the event with the - TypeManager so that GetFieldFromEvent can get at it. - - (TypeManager.RegisterPrivateFieldOfEvent): Implement to - keep track of the private field associated with an event which - has no accessors. - - (TypeManager.GetPrivateFieldOfEvent): Implement to get at the - private field. - - * ecore.cs (GetFieldFromEvent): RE-write to use the above methods. - -2002-07-10 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Binary.EmitBranchable): this routine emits the - Binary expression in a branchable context. This basically means: - we need to branch somewhere, not just get the value on the stack. - - This works together with Statement.EmitBoolExpression. - - * statement.cs (Statement.EmitBoolExpression): Use - EmitBranchable. - -2002-07-09 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (For): Reduce the number of jumps in loops. - - (For): Implement loop inversion for the For statement. - - (Break): We can be breaking out of a Try/Catch controlled section - (foreach might have an implicit try/catch clause), so we need to - use Leave instead of Br. - - * ecore.cs (FieldExpr.AddressOf): Fix for test-139 (augmented - now). If the instace expression supports IMemoryLocation, we use - the AddressOf method from the IMemoryLocation to extract the - address instead of emitting the instance. - - This showed up with `This', as we were emitting the instance - always (Emit) instead of the Address of This. Particularly - interesting when This is a value type, as we dont want the Emit - effect (which was to load the object). - -2002-07-08 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs: Pass the entry point to the DefinePInvokeMethod - - * statement.cs (Checked): Set the CheckedState during the resolve - process too, as the ConvCast operations track the checked state on - the resolve process, and not emit. - - * cs-parser.jay (namespace_member_declaration): Flag that we have - found a declaration when we do. This is used to flag error 1529 - - * driver.cs: Report ok when we display the help only. - -2002-07-06 Andrew Birkett <adb@tardis.ed.ac.uk> - - * cs-tokenizer.cs (xtoken): Improve handling of string literals. - -2002-07-04 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs (define): We also have to track locally the - defines. AllDefines is just used for the Conditional Attribute, - but we also need the local defines for the current source code. - -2002-07-03 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (While, For, Do): These loops can exit through a - Break statement, use this information to tell whether the - statement is the last piece of code. - - (Break): Flag that we break. - - * codegen.cs (EmitContexts): New `Breaks' state variable. - -2002-07-03 Martin Baulig <martin@gnome.org> - - * class.cs (TypeContainer.MethodModifiersValid): Allow override - modifiers in method declarations in structs. Otherwise, you won't - be able to override things like Object.Equals(). - -2002-07-02 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Method, Property, Indexer): Do not allow the public - modifier to be used in explicit interface implementations. - - (TypeContainer.MethodModifiersValid): Catch virtual, abstract and - override modifiers in method declarations in structs - -2002-07-02 Andrew Birkett <adb@tardis.ed.ac.uk> - - * cs-tokenizer.cs (adjust_int, adjust_real): Do not abort on - integer or real overflow, report an error - -2002-07-02 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.InitCoreTypes): When compiling - corlib, dynamically call AssemblyBuilder.SetCorlibTypeBuilders() - to tell the runtime about our newly created System.Object and - System.ValueType types. - -2002-07-02 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (This): Use Stobj/Ldobj when we are a member of a - struct instead of Ldarg/Starg. - -2002-07-02 Martin Baulig <martin@gnome.org> - - * expression.cs (Indirection.Indirection): Call - TypeManager.TypeToCoreType() on `expr.Type.GetElementType ()'. - -2002-07-02 Martin Baulig <martin@gnome.org> - - * expression.cs (ArrayAccess.EmitStoreOpcode): If the type is a - ValueType, call TypeManager.TypeToCoreType() on it. - (Invocations.EmitParams): Call TypeManager.TypeToCoreType() on - the OpCodes.Newarr argument. - -2002-07-02 Martin Baulig <martin@gnome.org> - - * expression.cs (Invocation.EmitCall): When compiling corlib, - replace all calls to the system's System.Array type to calls to - the newly created one. - - * typemanager.cs (TypeManager.InitCodeHelpers): Added a few more - System.Array methods. - (TypeManager.InitCoreTypes): When compiling corlib, get the methods - from the system's System.Array type which must be replaced. - -Tue Jul 2 19:05:05 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * typemanager.cs: load unverifiable_code_ctor so we can build - corlib using the correct type. Avoid using GetTypeCode() with - TypeBuilders. - * rootcontext.cs: uses TypeManager.unverifiable_code_ctor and - TypeManager.object_type to allow building corlib. - -Tue Jul 2 19:03:19 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * ecore.cs: handle System.Enum separately in LoadFromPtr(). - -2002-07-01 Martin Baulig <martin@gnome.org> - - * class.cs: Make the last change actually work, we need to check - whether `ifaces != null' to avoid a crash. - -Mon Jul 1 16:15:03 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * class.cs: when we build structs without fields that implement - interfaces, we need to add the interfaces separately, since there is - no API to both set the size and add the interfaces at type creation - time. - -Mon Jul 1 14:50:47 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * expression.cs: the dimension arguments to the array constructors - need to be converted if they are a long. - -Mon Jul 1 12:26:12 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * class.cs: don't emit ldarg.0 if there is no parent constructor - (fixes showstopper for corlib). - -2002-06-29 Martin Baulig <martin@gnome.org> - - MCS now compiles corlib on GNU/Linux :-) - - * attribute.cs (Attribute.ApplyAttributes): Treat Accessors like Method, - ie. check for MethodImplOptions.InternalCall. - - * class.cs (TypeContainer.DefineType): When compiling corlib, both parent - and TypeManager.attribute_type are null, so we must explicitly check - whether parent is not null to find out whether it's an attribute type. - (Property.Emit): Always call Attribute.ApplyAttributes() on the GetBuilder - and SetBuilder, not only if the property is neither abstract nor external. - This is necessary to set the MethodImplOptions on the accessor methods. - (Indexer.Emit): Call Attribute.ApplyAttributes() on the GetBuilder and - SetBuilder, see Property.Emit(). - - * rootcontext.cs (RootContext.PopulateTypes): When compiling corlib, don't - populate "System.Object", "System.ValueType" and "System.Attribute" since - they've already been populated from BootCorlib_PopulateCoreTypes(). - -2002-06-29 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.ImplicitReferenceConversionExists): If expr - is the NullLiteral, we also need to make sure that target_type is not - an enum type. - -2002-06-29 Martin Baulig <martin@gnome.org> - - * rootcontext.cs (RootContext.ResolveCore): We must initialize - `TypeManager.multicast_delegate_type' and `TypeManager.delegate_type' - before calling BootstrapCorlib_ResolveDelegate (). - -2002-06-27 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * statement.cs: fixed build-breaker. All tests passed ok. - -2002-06-27 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.VerifyUnManaged): Added explicit check - for System.Decimal when compiling corlib. - -2002-06-27 Martin Baulig <martin@gnome.org> - - * statement.cs (Switch.TableSwitchEmit): Make this work with empty - switch blocks which contain nothing but a default clause. - -2002-06-26 Andrew <adb@tardis.ed.ac.uk> - - * ../errors/cs1501-3.cs: Added new test for struct ctr typechecks. - -2002-06-27 Martin Baulig <martin@gnome.org> - - * ecore.cs (PropertyExpr.PropertyExpr): Call - TypeManager.TypeToCoreType() on the `pi.PropertyType'. - - * typemanager.cs (TypeManager.TypeToCoreType): Return if the type - is already a TypeBuilder. - -2002-06-27 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.ImplicitReferenceConversionExists): Use - `target_type == TypeManager.array_type', not IsAssignableFrom() in - the "from an array-type to System.Array" case. This makes it work - when compiling corlib. - -2002-06-27 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.SimpleNameResolve): If the expression is a - non-static PropertyExpr, set its InstanceExpression. This makes - the `ICollection.Count' property work in System/Array.cs. - -2002-06-25 Andrew Birkett <adb@tardis.ed.ac.uk> - - * driver.cs: Made error handling more consistent. Errors now - tracked by Report class, so many methods which used to return int - now return void. Main() now prints success/failure and - errors/warnings message. - - Renamed '--probe' compiler argument to '--expect-error'. Removed - the magic number return values (123 and 124). Now, if the - expected error occurs, the compiler exits with success (exit value - 0). If the compilation completes without seeing that particular - error, the compiler exits with failure (exit value 1). The - makefile in mcs/errors has been changed to handle the new behaviour. - - * report.cs: Made 'expected error' number a property and renamed - it from 'Probe' to 'ExpectedError'. - - * genericparser.cs: Removed error handling support, since it is - now all done by Report class. - - * cs-parser.jay, mb-parser.jay: Errors are tracked by Report - class, so parse() no longer returns an int. - - * namespace.cs: Use Report.Error instead of GenericParser.error - -2002-06-22 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer.AddMethod, TypeContainer.AddIndexer, - TypeContainer.AddOperator): At the front of the list put the - explicit implementations, so they get resolved/defined first. - -2002-06-21 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer.VerifyImplements): Verifies that a given - interface type is implemented by this TypeContainer. Used during - explicit interface implementation. - - (Property.Define, Indexer.Define, Method.Define): Validate that - the given interface in the explicit implementation is one of the - base classes for the containing type. - - Also if we are explicitly implementing an interface, but there is - no match in the pending implementation table, report an error. - - (Property.Define): Only define the property if we are - not explicitly implementing a property from an interface. Use the - correct name also for those properties (the same CSC uses, - although that is really not needed). - - (Property.Emit): Do not emit attributes for explicitly implemented - properties, as there is no TypeBuilder. - - (Indexer.Emit): ditto. - - Hiding then means that we do not really *implement* a pending - implementation, which makes code fail. - -2002-06-22 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.Constantify): Call TypeManager.TypeToCoreType() on - the return value of Object.GetType(). [FIXME: we need to do this whenever - we get a type back from the reflection library]. - -Fri Jun 21 13:37:57 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * typemanager.cs: make ExpandInterfaces() slip duplicated interfaces. - -2002-06-20 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs: Return null if we can not look up the type. - - * class.cs (TypeContainer.GetClassBases): Use ExpandInterfaces on - the interface types found. - - * interface.cs (Interface.GetInterfaceBases): Use ExpandInterfaces on the - interface types found. - - * typemanager.cs (GetInterfaces): Make this routine returns alll - the interfaces and work around the lame differences between - System.Type and System.Reflection.Emit.TypeBuilder in the results - result for GetInterfaces. - - (ExpandInterfaces): Given an array of interface types, expand and - eliminate repeated ocurrences of an interface. This expands in - context like: IA; IB : IA; IC : IA, IB; the interface "IC" to - be IA, IB, IC. - -2002-06-21 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.EnumToUnderlying): It's now safe to call this function - on System.Enum. - -2002-06-21 Martin Baulig <martin@gnome.org> - - * typemanager.cs (TypeManager.TypeToCoreType): New function. When compiling corlib - and called with one of the core types, return the corresponding typebuilder for - that type. - - * expression.cs (ArrayAccess.DoResolve): Call TypeManager.TypeToCoreType() on the - element type. - -2002-06-21 Martin Baulig <martin@gnome.org> - - * ecore.cs (Expression.ExplicitReferenceConversionExists): Use - `target_type.IsArray' instead of `target_type.IsSubclassOf (TypeManager.array_type)'. - (Expression.ConvertReferenceExplicit): Likewise. - - * expression.cs (ElementAccess.DoResolve): Likewise. - (ElementAccess.DoResolveLValue): Likewise. - -2002-06-10 Martin Baulig <martin@gnome.org> - - * interface.cs (Interface.PopulateIndexer): When creating the setter, we need to - add the "value" parameter to the parameter list. - - * statement.cs (Fixed.Emit): Pass the return value of the child block's Emit() - to our caller. - -2002-06-19 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ArrayCreation.ExpressionToArrayArgument): Convert - the argument to an int, uint, long or ulong, per the spec. Also - catch negative constants in array creation. - -Thu Jun 20 17:56:48 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * class.cs: do not allow the same interface to appear twice in - the definition list. - -Wed Jun 19 22:33:37 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * ecore.cs: don't use ldlen with System.Array. - -Wed Jun 19 20:57:40 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * ecore.cs: stobj requires a type argument. Handle indirect stores on enums. - -Wed Jun 19 20:17:59 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * modifiers.cs: produce correct field attributes for protected - internal. Easy fix so miguel can work on ther harder stuff:-) - -2002-06-18 Miguel de Icaza <miguel@ximian.com> - - * pending.cs: New file. Move the code from class.cs here. - Support clearning the pending flag for all methods (when not doing - explicit interface implementation). - -Tue Jun 18 10:36:22 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * rootcontext.cs: added a couple more types needed to bootstrap. - -2002-06-17 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (GetConstructor): Use DeclaredOnly to look the - constructor in the type, instead of any constructor in the type - hierarchy. Thanks to Paolo for finding this bug (it showed up as - a bug in the Mono runtime when applying the params attribute). - -2002-06-16 Rafael Teixeira <rafaelteixeirabr@hotmail.com> - * changed namespace.cs to use "GenericParser.error(...)" instead of "CSharpParser.error(...)" - -2002-06-14 Rachel Hestilow <hestilow@ximian.com> - - * expression.cs (Unary.ResolveOperator): Use TypeManager - to resolve the type. - -2002-06-13 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (enum_member_declaration): Pass in the attributes - attached. - - * enum.cs (AddEnumMember): Add support to store the attributes associated - with each member too. - - * attribute.cs (CheckAttribute, ApplyAttributes): Update to handle - field builders too - this takes care of the enum member case. - -2002-06-10 Rachel Hestilow <hestilow@ximian.com> - - * typemanager.cs (TypeManager.VerifyUnManaged): Allow - address-of operator on both value types and pointers. - -2002-06-10 Martin Baulig <martin@gnome.org> - - * interface.cs (Interface.PopulateIndexer): Add the indexer's - PropertyBuilder to the `property_builders' list. - - * expression.cs (Indexers.GetIndexersForTypeOrInterface): New private method. - (Indexers.GetIndexersForType): Call GetIndexersForTypeOrInterface() on the - `lookup_type' and all its interfaces. Unfortunately, Type.FindMembers() won't - find any indexers which are inherited from an interface. - -2002-06-09 Martin Baulig <martin@gnome.org> - - * const.cs (Const.LookupConstantValue): Convert `Expr' to a literal of - the same type as the constant if necessary. There's also a test-130.cs - for this. - - * enum.cs (Enum.ChangeEnumType): Moved to typemanager.cs and made public. - - * typemanager.cs (TypeManager.ChangeType): Previously known as - Enum.ChangeEnumType(). - -2002-06-09 Martin Baulig <martin@gnome.org> - - * expression.cs (Cast.TryReduce): Added support for consts. - -2002-06-08 Ravi Pratap <ravi@ximian.com> - - * class.cs (Accessor): Hold attributes information so we can pass - it along. - - * cs-parser.jay (get_accessor_declaration, set_accessor_declaration): - Modify to pass in attributes attached to the methods. - - (add_accessor_declaration, remove_accessor_declaration): Ditto. - - * attribute.cs (ApplyAttributes, CheckAttribute): Update accordingly - to handle the Accessor kind :-) - - * class.cs (Property.Emit, Event.Emit): Apply attributes to the accessors - -2002-06-08 Martin Baulig <martin@gnome.org> - - * expression.cs (Unary.TryReduceNegative): Added support for - ULongConstants. - -2002-06-08 Martin Baulig <martin@gnome.org> - - * enum.cs (Enum.LookupEnumValue): Don't report an error if the - name can't be found in the `defined_names' - the caller will do a - MemberLookup in this case and thus find methods in System.Enum - such as Enum.IsDefined(). - -2002-06-08 Martin Baulig <martin@gnome.org> - - * enum.cs (Enum.ChangeEnumType): This is a custom version of - Convert.ChangeType() which works with TypeBuilder created types. - (Enum.LookupEnumValue, Enum.Define): Use it here. - - * class.cs (TypeContainer.RegisterRequiredImplementations): Added - `TypeBuilder.BaseType != null' check. - (TypeContainer.FindMembers): Only lookup parent members if we - actually have a parent. - (Method.EmitDestructor): Added `ec.ContainerType.BaseType != null' check. - (ConstructorInitializer.Resolve): Likewise. - - * interface.cs (Interface.FindMembers): Added - `TypeBuilder.BaseType != null' check. - - * rootcontext.cs (RootContext.ResolveCore): Added - "System.Runtime.CompilerServices.IndexerNameAttribute" to - classes_second_stage. - - * typemanager.cs (TypeManager.InitCoreTypes): Don't initialize - debug_type and trace_type when compiling with --nostdlib. - -2002-06-07 Martin Baulig <martin@gnome.org> - - * class.cs (TypeContainer): Added `have_nonstatic_fields' field. - (AddField): Set it to true when adding a non-static field. - (DefineType): Use `have_nonstatic_fields' to find out whether we - have non-static fields, not `Fields != null'. - -2002-06-02 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (SimpleNameResolve): Removed simple bug (we were - dereferencing a null on the static-field code path) - -2002-05-30 Martin Baulig <martin@gnome.org> - - * codegen.cs (InitMonoSymbolWriter): Added `string[] args' argument - to take command line arguments. Use reflection to call the new - custom `Initialize' function on the symbol writer and pass it the - command line arguments. - - * driver.cs (--debug-args): New command line argument to pass command - line arguments to the symbol writer. - -2002-05-28 Miguel de Icaza <miguel@ximian.com> - - * assign.cs (DoResolve): Forgot to do the implicit conversion to - the target type for indexers and properties. Thanks to Joe for - catching this. - -2002-05-27 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (MethodFlags): returns the method flags - (Obsolete/ShouldIgnore) that control warning emission and whether - the invocation should be made, or ignored. - - * expression.cs (Invocation.Emit): Remove previous hack, we should - not do this on matching a base type, we should do this based on an attribute - - Only emit calls to System.Diagnostics.Debug and - System.Diagnostics.Trace if the TRACE and DEBUG defines are passed - on the command line. - - * rootcontext.cs: Global settings for tracing and debugging. - - * cs-tokenizer.cs (define): New utility function to track - defines. Set the global settings for TRACE and DEBUG if found. - -2002-05-25 Ravi Pratap <ravi@ximian.com> - - * interface.cs (Populate*): Pass in the TypeContainer as well as - the DeclSpace as parameters so that we can create EmitContexts and - then use that to apply attributes etc. - - (PopulateMethod, PopulateEvent, PopulateProperty) - (PopulateIndexer): Apply attributes everywhere. - - * attribute.cs (CheckAttribute): Include InterfaceMethod, InterfaceEvent - etc. - - (ApplyAttributes): Update accordingly. - - We now apply interface attributes for all members too. - -2002-05-26 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Indexer.Define); Correctly check if we are explicit - implementation (instead of checking the Name for a ".", we - directly look up if the InterfaceType was specified). - - Delay the creation of the PropertyBuilder. - - Only create the PropertyBuilder if we are not an explicit - interface implementation. This means that explicit interface - implementation members do not participate in regular function - lookups, and hence fixes another major ambiguity problem in - overload resolution (that was the visible effect). - - (DefineMethod): Return whether we are doing an interface - implementation. - - * typemanager.cs: Temporary hack until we get attributes in - interfaces (Ravi is working on that) and we get IndexerName - support in interfaces. - - * interface.cs: Register the indexers as properties. - - * attribute.cs (Attribute.Resolve): Catch the error, and emit a - warning, I have verified that this is a bug in the .NET runtime - (JavaScript suffers of the same problem). - - * typemanager.cs (MemberLookup): When looking up members for - interfaces, the parent of an interface is the implicit - System.Object (so we succeed in searches of Object methods in an - interface method invocation. Example: IEnumerable x; x.ToString - ()) - -2002-05-25 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Event): Events should also register if they do - implement the methods that an interface requires. - - * typemanager.cs (MemberLookup); use the new GetInterfaces - method. - - (GetInterfaces): The code used to lookup interfaces for a type is - used in more than one place, factor it here. - - * driver.cs: Track the errors at the bottom of the file, we kept - on going. - - * delegate.cs (NewDelegate.Emit): We have to emit a null as the - instance if the method we are calling is static! - -2002-05-24 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs (ApplyAttributes): Make this function filter out - the IndexerName attribute (as that attribute in reality is never - applied) and return the string constant for the IndexerName - attribute. - - * class.cs (TypeContainer.Emit): Validate that all the indexers - have the same IndexerName attribute, and if so, set the - DefaultName attribute on the class. - - * typemanager.cs: The return value might contain other stuff (not - only methods). For instance, consider a method with an "Item" - property and an Item method. - - * class.cs: If there is a problem with the parameter types, - return. - -2002-05-24 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (ImplicitConversionExists): Wrapper function which also - looks at user defined conversion after making a call to - StandardConversionExists - we need this for overload resolution. - - * expression.cs : Update accordingly the various method calls. - - This fixes 2 bugs filed against implicit user defined conversions - -2002-05-22 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: Track the result of the assignment. - -2002-05-21 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (MemberAccess): Improved error reporting for - inaccessible members. - -2002-05-22 Martin Baulig <martin@gnome.org> - - * makefile (mcs-mono2.exe): New target. This is mcs compiled with - itself with debugging support. - -2002-05-22 Martin Baulig <martin@gnome.org> - - * typemanager.cs ("System.Runtime.InteropServices.StructLayoutAttribute"): - Removed, this isn't needed anymore. - -2002-05-20 Martin Baulig <martin@gnome.org> - - * typemanager.cs (InitEnumUnderlyingTypes): "System.Char" can't - be underlying type for an enum. - -2002-05-20 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (InitEnumUnderlyingTypes): New helper function - that splits out the loading of just the core types. - - * rootcontext.cs (ResolveCore): Split the struct resolution in - two, so we can load the enumeration underlying types before any - enums are used. - - * expression.cs (Is): Bandaid until we fix properly Switch (see - bug #24985 for details). - - * typemanager.cs (ImplementsInterface): The hashtable will contain - a null if there are no interfaces implemented. - -2002-05-18 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay (indexer_declarator): It is fine to have array - parameters - -2002-05-17 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs: (RegisterBuilder): New function used to register - TypeBuilders that implement interfaces. Since - TypeBuilder.GetInterfaces (as usual) does not work with lame - Reflection.Emit. - (AddUserType): register interfaces. - - (ImplementsInterface): Use the builder_to_ifaces hash if we are - dealing with TypeBuilder. Also, arrays are showing up as - SymbolTypes, which are not TypeBuilders, but whose GetInterfaces - methods can not be invoked on them! - - * ecore.cs (ExplicitReferenceConversionExists): Made public. - (ImplicitReferenceConversionExists): Split out from - StandardConversionExists. - - * expression.cs (As): We were only implementing one of the three - cases for the as operator. We now implement them all. - (Is): Implement the various other cases for Is as well. - - * typemanager.cs (CACHE): New define used to control if we want or - not the FindMembers cache. Seems to have a negative impact on - performance currently - - (MemberLookup): Nested types have full acess to - enclosing type members - - Remove code that coped with instance/static returns for events, we - now catch this in RealFindMembers. - - (RealFindMembers): only perform static lookup if the instance - lookup did not return a type or an event. - -2002-05-17 Miguel de Icaza <miguel@ximian.com> - - * assign.cs (CompoundAssign): We pass more semantic information - now to Compound Assignments than we did before: now we have all - the information at hand, and now we resolve the target *before* we - do the expression expansion, which allows the "CacheValue" method - to have the effect we intended (before, a [x] += 1 would generate - two differen ArrayAccess expressions from the ElementAccess, - during the resolution process). - - (CompoundAssign.DoResolve): Resolve target and original_source here. - -2002-05-16 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ArrayAccess): dropped debugging information. - - * typemanager.cs: Small bug fix: I was always returning i_members, - instead of one of i_members or s_members (depending on which had - the content). - - * assign.cs (IAssignMethod.CacheTemporaries): New method. This - method is invoked before any code generation takes place, and it - is a mechanism to inform that the expression will be invoked more - than once, and that the method should use temporary values to - avoid having side effects - - (Assign.Emit): Call CacheTemporaries in the IAssignMethod. - - * ecore.cs (Expression.CacheTemporaries): Provide empty default - implementation. - - * expression.cs (Indirection, ArrayAccess): Add support for - CacheTemporaries in these two bad boys. - - * ecore.cs (LoadFromPtr): figure out on our own if we need to use - ldobj or ldind_ref. - (StoreFromPtr): Handle stobj as well. - - * expression.cs (UnaryMutator): Share more code. - - * typemanager.cs (FindMembers): Thanks to Paolo for tracking this - down: I was not tracking the Filter function as well, which - was affecting the results of the cache. - -2002-05-15 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs: Remove the hack to handle the CharSet property on - StructLayouts. - -2002-05-14 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs (DoResolve): More uglyness, we now only try to - resolve the attribute partially, to extract the CharSet - information (only if we are a StructLayout attribute). Otherwise - - (GetExtraTypeInfo): Add some code to conditionally kill in the - future this. I am more and more convinced that the .NET - framework has special code to handle the attribute setting on - certain elements. - - * expression.cs (IsParamsMethodApplicable): Revert my previous - foreach change here, it was wrong. - -2002-05-13 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: (pp_primary): Eat the ')' at the end. - (pp_expr): do not abort on unknown input, just return. - (eval): abort if there are pending chars. - - * attribute.cs (Attribute.Resolve): Positional parameters are - optional. Deal with that case. - - * class.cs (DefineType): Call Attribute.GetExtraTypeInfo to fetch - the Ansi/Unicode/Auto information for the type. - - (TypeContainer.DefineType): instantiate the EmitContext here, as - we will be using it during the type definition (to resolve - attributes) and during the emit phase. - - * attribute.cs (Attribute.GetExtraTypeInfo): This routine is used - to pull type information out of the attributes - - (Attribute.Resolve): track the constructor builder, and allow for - multiple invocations (structs and classes will use this). - - * ecore.cs (MemberLookupFinal): new version with all the - parameters customizable. - - * expression.cs (New.DoResolve): Use MemberLookupFinal to locate - constructors. Return if the result value is null (as the error - would have been flagged already by MemberLookupFinal) - - Do not allow instances of abstract classes or interfaces to be - created. - - * class.cs: (MethodSignature.InheritableMemberSignatureCompare): - We have to compare the assembly property here when dealing with - FamANDAssem and Assembly access modifiers, because we might be - creating an assembly from *modules* (that means that we are not - getting TypeBuilders for types defined in other modules that are - part of this assembly). - - (Method.Emit): If the method is marked abstract and has a body, - emit an error. - - (TypeContainer.DefineMembers): If both the defined member and the - parent name match are methods, then do not emit any warnings: let - the Method.Define routine take care of flagging warnings. But if - there is a mismatch (method overrides something else, or method is - overriwritten by something, then emit warning). - - (MethodSignature.MemberSignatureCompare): If the sig.ret_type is - set to null, this means `do not check for the return type on the - signature'. - - (Method.Define): set the return type for the method signature to - null, so that we get methods with the same name and parameters and - different return types. This is used to flag warning 114 (you are - hiding a method, and you probably want to use the new/override - keywords instead). - - * typemanager.cs (MemberLookup): Implemented proper access - control, closing a long standing set of bug reports. The problem - was that the Framework only has two bits: Public and NonPublic, - and NonPublic includes private and protected methods, but we need - to enforce the FamANDAssem, FamOrAssem and Family. - -2002-05-11 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (GotoCase): Return true: Ammounts to giving up - knowledge on whether we return or not, and letting the other case - be responsible for it. - -2002-05-10 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Do not load directories for each file processed, only - do it if there is a pattern. - - * ecore.cs: Report readonly assigns here as well, as we might have - been resolved only by MemberAccess. - - (SimpleName.SimpleNameResolve): Also be useful for LValue - resolution. We need this to propagate assign to local readonly variables - - * typemanager.cs: Use a ptrhashtable for the criteria, because we - do not want to reuse potential criteria memory. - - * class.cs (MyEventBuilder): Set reflected_type; - - * ecore.cs (Constantify): Added support for constifying bools. - - (RootContext.LookupType): Added a cache for values looked up in - the declaration space. - - * typemanager.cs (FindMembers): Now is a front-end to - RealFindMembers, and provides a two-level hashtable-based cache to - the request. - - 15% performance improvement: from 22.5 to 19.2 seconds. - - * expression.cs (IsParamsMethodApplicable): use foreach. - (Invocation.DoResolve): ditto. - (New.DoResolve): ditto. - (ArrayCreation.DoResolve): ditto. - - * ecore.cs (FindMostEncompassingType): use foreach. - - * delegate.cs (NewDelegate.DoResolve): Use foreach - - * ecore.cs (Expression.FindMostSpecificSource): Use foreach. - (RemoveMethods): use foreach. - - * expression.cs (Invocation.MakeUnionSet): Optimization: Use two - nested foreach statements instead of for, and also break out of - the inner loop once a match is found. - - (Invocation.OverloadResolve): Use foreach, simplify the code. - -2002-05-08 Miguel de Icaza <miguel@ximian.com> - - * cfold.cs (BinaryFold): During an enumeration evaluation context, - we actually unwrap the expression to allow for extra information - to be extracted. - - * expression.cs: Use Shr_Un on unsigned operations. - -2002-05-08 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (FindMostEncompass*): Fix trivial bug where the set of - applicable operators was not being considered correctly. This closes - the bug Miguel reported. - -Wed May 8 16:40:50 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * attribute.cs: check that the type derives from System.Attribute - and report the correct error in that case (moved the duplicate code to - its own method, too). - -Wed May 8 11:50:31 CEST 2002 Paolo Molaro <lupus@ximian.com> - - * attribute.cs: lookup attribute type name as the spec says: first the - bare attribute name and then name + "Attribute" (nant compiles with - mcs after this fix). - -2002-05-07 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Unary.TryReduceNegative): Ah! Tricky! Tricky! - Because of the way we parse things, we should try to see if a - UIntConstant can fit in an integer. - -2002-05-07 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (GetConversionOperators): Do not pick up op_True operators - when we are in an explicit context. - - (ConvertReferenceExplicit): When converting from Iface type S to Class - T make sure the rules are implemented as an OR. - - * parameter.cs (ParameterType): Make it a property for now although the - purpose really isn't anything immediate. - - * expression.cs (Is*Applicable): Do better checking on the parameter type - of a ref/out parameter. The ones from the system assemblies are already - marked with the correct type so we don't need to do any correction. - - * ecore.cs (StandardConversionExists): Conversion from Interface types to - the object type is standard too so include that. - -2002-05-06 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (StandardConversionExists): Augment with missing code: - deal with IntConstant, LongConstants and Enumerations. - - * assign.cs: Report the error, instead of failing silently - - * rootcontext.cs (AddGlobalAttributes): Track attributes on the - typecontainer that they are declared, because the - typecontainer/namespace will have the list of using clauses that - need to be applied. - - Assembly Attributes were escaping the normal registration - mechanism. - - (EmitCode): Apply attributes within an EmitContext that represents - the container they were declared on. - - * cs-parser.jay: Track bases for structs. How did I get this wrong? - -2002-05-06 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (FindMostEncompassingType, FindMostEncompassedType): - Revamp completely - make much cleaner as we now operate only - on a set of Types. - - (FindMostSpecificSource, FindMostSpecificTarget): New methods - to implement the logic detailed in the spec more correctly. - - (UserDefinedConversion): Update accordingly. - -2002-05-06 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: Return flow analysis information up. - - * cs-tokenizer.cs (adjust_real): Share code between LITERAL_DOUBLE - and the default. - - (token): Do not consume an extra character before calling - decimal_digits. - -2002-05-06 Piers Haken <piersh@friskit.com> - - * cs-parser.jay: add 'override' attribute to System.Object.Finalize - -2002-05-06 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Constructor.Emit): Set the IsStatic flag in the - EmitContext during the instance constructor initializer - resolution, to stop access to instance variables. - - This is mandated by the spec, last paragraph of the `constructor - initializers' section. - -2002-05-05 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay, class.cs (Accessor): new class used to represent - an accessor (get or set). In the past we used `null' to represent - a missing accessor. But this is ambiguous because there was no - way to tell in abstract indexers/properties if one of them was - specified. - - Now there is a way of addressing that. - - * expression.cs (Indexers.GetIndexersForType): Use TypeManager.MemberLookup - instead of FindMembers. - - * class.cs (TypeContainer.EmitFieldInitializer): Do not typecast - the result of Assign.Resolve as Assign, but rather as ExpressionStatement. - - * attribute.cs: Treat indexers and properties as the same in terms - of applying attributes - - * ecore.cs (FindMostEncompassedType): Use statically initialized - EmptyExpressions()s like we do elsewhere to avoid creating useless - objects (and we take this out of the tight loop). - - (GetConversionOperators): Move the code to extract the actual - operators to a separate routine to clean things up. - -2002-05-04 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (FieldExpr): Remove un-needed tests for null, since now - events are always registered FieldBuilders. - - * class.cs (FieldBase): New class shared by Fields - - * delegate.cs: If we are a toplevel delegate, use our full name. - If we are a nested delegate, then only use our tail name. - -2002-05-02 Ravi Pratap <ravi@ximian.com> - - * expression.cs (IsApplicable): Ensure that we add the "&" to - ref/out types before comparing it with the type of the argument. - - (IsParamsMethodApplicable): Ditto. - - (Argument.Type): Use TypeManager.LookupType instead of Type.GetType - - silly me ;-) - - * delegate.cs : Handle the case when we have more than one applicable - method. Flag an error only when we finish checking all. - -2002-05-02 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Add support for boolean static initializers. - -2002-05-01 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs: Use proper cast for Events, since we use a MyEventBuilder. - - * parameter.cs (ComputeParameterTypes, - ComputeAndDefineParameterTypes): Better error handling: now we - clear the `types' cache if we fail during any of the type lookups. - We also return the status code correctly to our caller - - * delegate.cs: If we fail to define a delegate, abort the extra - steps. - - * expression.cs (Binary.ResolveOperator): for - operator==(object,object) and operator !=(object, object) we also - have to verify that there is an implicit conversion from one to - the other. - - (ArrayAccess.DoResolve): Array Access can operate on - non-variables. - -2002-04-30 Miguel de Icaza <miguel@ximian.com> - - * assign.cs (CompoundAssign): A new class used as a "flag" that - the assignment actually is happening as part of a compound - assignment operator. - - During compound assignment, a few new rules exist to enable things - like: - - byte b |= 1 + 2 - - From the spec: - - x op= y can be evaluated as x = (T) (x op y) (ie, an explicit cast - to the type of x) if y is implicitly convertible to the type of x, - and the operator is a builtin operator and the return type of the - operator is explicitly convertible to the type of x. - - * rootcontext.cs: Reset warning level to 2. 4 catches various - "interesting" features in mcs, we must clean this up at some - point, but currently am trying to kill other bugs ;-) - - * ecore.cs (SimpleName.SimpleNameResolve): Perform member lookups - in container classes as well. - - * expression.cs (Binary.ResolveOperator): Handle string case - before anything else (as operator overloading does emit an error - before doing anything else). - - This code could go away when we move to a table driven model, but - i could not come up with a good plan last night. - -2002-04-30 Lawrence Pit <loz@cable.a2000.nl> - - * typemanager.cs (CSharpName): reimplementation using regex. - * class.cs: added null check for fields in Emit - * rootcontext.cs: set warninglevel to 4 - -2002-04-29 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (CSharpName): reimplemented with Lupus - suggestion. - -2002-04-28 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (If): correclty implement Resolve, because we were - not catching sem errors in there. The same process is needed - everywhere else. - (Return, StatementExpression, For, While, Do, Throw, Lock): Implement Resolve - - - (Statement.Warning_DeadCodeFound): Factorize code. - (While): Report dead code here too. - - (Statement): Added Resolve virtual method to allow - for resolution split from the emit code. - -2002-04-26 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (EmitBoolExpression): No longer try to resolve the - expression here. - (MakeBoolean): New utility function that resolve, implicitly - converts to boolean and tags the expression. - - - (If, Do): Implement dead code elimination. - (While): Implement loop inversion - - (Do, While, For, If): Resolve the expression prior to calling our - code generation. - -2002-04-22 Lawrence Pit <loz@cable.a2000.nl> - - * class.cs: - - added method Report28 (warning: program has more than one entry point) - - added method IsEntryPoint, implements paragraph 10.1 of the spec - - modified method Method.Define, the part at the end of the method - - * rootcontext.cs: added static public Location EntryPointLocation; - - * ../errors/cs0028.cs : Add test case for the above warning. - - * typemanager.cs: - - modified method CSharpName to allow arrays of primitive type to - be printed nicely (e.g. instead of System.Int32[][] it now prints - int[][]) - - added method CSharpSignature: returns the signature of a method - in string format to be used in reporting errors, warnings, etc. - - * support.cs: InternalParameters.ParameterDesc variable tmp initialized - with String.Empty. - -2002-04-26 Ravi Pratap <ravi@ximian.com> - - * delegate.cs (Define): Fix extremely silly bug where I was - setting the type of the 'object' parameter of the BeginInvoke - method to System.IAsyncResult instead of System.Object ;-) - -2002-04-26 Miguel de Icaza <miguel@ximian.com> - - * class.cs (ConstructorInitializer.Resolve): Also use DeclaredOnly - here. - - (Constructor.Emit): return if we fail to initialize the - constructor. Another door closed! - - * expression.cs (New.DoResolve): Improve error message (from -6 to - 1501). Use DeclaredOnly lookup to find the exact constructor. - - * typemanager.cs (MemberLookup): If DeclaredOnly is set, do not - loop. This is useful. - - * cs-parser.jay: Adjust the default parameters so that destructors - have the proper signature. - -2002-04-26 Martin Baulig <martin@gnome.org> - - * driver.cs (LoadAssembly): If `assembly' contains any characters - which are only valid in path names and not in assembly names - (currently slash, backslash and point), use Assembly.LoadFrom () - instead of Assembly.Load () on the `assembly' (before iteration - over the link_paths). - -2002-04-26 Martin Baulig <martin@gnome.org> - - * cs-tokenizer.cs (is_hex): Correctly handle lowercase chars. - -2002-04-25 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Property): use the new typemanager.MemberLookup - - (TypeContainer.MemberLookup): Implement using the - TypeManager.MemberLookup now. - - * typemanager.cs: Make MemberLookup a function of the TypeManager, - and return MemberInfos, so that these can be used without an - EmitContext (what we had before). - -2002-04-24 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Fix the case where the argument to params if the - type of the params. I omitted handling this before. Fixed - -2002-04-22 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Call BootCorlib_PopulateCoreType - - * class.cs (Property.CheckBase): Check for properties only, not - for all members. - - * interface.cs: Temporary hack: try/catch around the - CustomAttributeBuilder, because I am getting an exception that I - do not understand. - - * rootcontext.cs (BootCorlib_PopulateCoreType): Populate some - types whose definitions are required to be there (attributes are - defined before standard types). - - Compute definitions as we boot the various types, as they are used - immediately (value_type class will need object_type, but if we do - not initialize object_type, we will pass a null, which will let - the runtime pick the System.Object from the existing corlib, which - is not what we want). - -2002-04-22 Patrik Torstensson <totte@labs2.com> - - * cs-tokenizer.cs: fixed a number of trim() issues. - -2002-04-22 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Argument.Type): Ensure that we return the correct - type when we have out or ref parameters [in which case we - append a "&"]. - -2002-04-22 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Property, Indexer): Allow extern modifier in there. - - * typemanager.cs (InitBaseTypes): Initializes object_type and - value_type, since those will be used early on during the bootstrap - process to compile corlib. - - (InitCoreTypes): Move code from here to InitBaseTypes. - -2002-04-21 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (PropertyExpr): Optimize calls to Array::get_Length on - single-dimension arrays as using the ldlen opcode. - - Daniel Lewis discovered this optimization. - - * typemanager.cs: Add signature for System.Array::get_Length - -2002-04-20 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * statement.cs: report the error when the foreach does not apply to an - array nor a collection. - -2002-04-19 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Add implicit conversions to the operator ~. - - * constant.cs (DecimalConstant.Emit): Emit decimal value. - - * typemanager.cs: Locate the decimal constructor. - -2002-04-17 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * attribute.cs: use the new property of TypeOf. - * expression.cs: added 'get' property around typearg. - - These changes fix a build breaker reported by NickD. Is this the - correct way to fix? If not, please, revert my changes and make it - work :-). - -2002-04-17 Miguel de Icaza <miguel@ximian.com> - - * attribute.cs: Add support for typeof in attribute invocations. - I am not sure that this is right though. - -2002-04-14 Duncan Mak <duncan@ximian.com> - - * cfold.cs (BinaryFold): Catch DivideByZeroException in the - Binary.Operator.Division case. - -2002-04-13 Ravi Pratap <ravi@ximian.com> - - * class.cs (DefineType): Ensure that we do a proper check on - attribute types and also register it with the TypeManager. - - (TypeContainer.Targets): The default for attribute types is - AttributeTargets.All. - - * attribute.cs (ApplyAttributes): Registering the attribute type - is done elsewhere, not when we discover we have a Usage attribute. - -2002-04-12 Ravi Pratap <ravi@ximian.com> - - * expression.cs (VerifyArgumentsCompat): Implement Miguel's suggestion - and get rid of is_delegate parameter. - - * everywhere : update. - -2002-04-12 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (compilation_unit): Revamp completely to use - some new ideas that I got from Rhys' grammar to solve the problems - with assembly level attributes. - - (outer_declaration): New grammar production. - - (attribute_sections): Add. - - (opt_attributes): Base on attribute_sections - - (namespace_declaration): Allow opt_attributes to tackle the case - when we have assembly level attributes - we are clever in this - regard now ;-) - - * attribute.cs (ApplyAttributes): Do not worry about assembly - attributes in the non-global context. - - * rootcontext.cs (AddGlobalAttributes): Go back to using this - instead of SetGlobalAttributes. - - * class.cs, rootcontext.cs : Ensure we define and generate - attribute types before anything else. - - * attribute.cs (CheckAttribute and GetValidPlaces): Handle the exception - and flag the new error -20 for the case when the attribute type - does not have valid targets specified. csc does not catch this. - - * ../errors/errors.txt : update for error # -20 - -2002-04-11 Ravi Pratap <ravi@ximian.com> - - * support.cs (InternalParameters.ParameterModifier): Do some null - checking and return sane values. - - * class.cs (Method.Define): If we are a PInvoke method, ensure - that we are static and extern. Report error # 601 - - * ../errors/cs0601.cs : Add test case for the above error. - -2002-04-07 Ravi Pratap <ravi@ximian.com> - - * rootcontext.cs (attribute_types): We need to keep type of - all attribute types separately and emit code for them first. - - (RegisterAttribute) : Implement. - - * class.cs (DefineType): Check if the current Type is a custom - attribute type and register it accordingly. - - * rootcontext.cs (AddGlobalAttributes): Fix silly bug where we were - adding the first attribute twice and rename to - - (SetGlobalAttributes): this. - - * rootcontext.cs (NamespaceLookup): Run through the aliases too and perform - lookups. - - * attribute.cs (ApplyAttributes): Take an additional argument telling us - if we are processing global arguments. Hmm, I am unsure of this. - -2002-04-12 Gonzalo Paniagua Javier <gonzalo@ximian.com> - - * expression.cs: added static array of strings to avoid calling - Enum.ToString () for Operator in Binary. Significant recover of - performance. - -2002-04-10 Miguel de Icaza <miguel@ximian.com> - - * class.cs (FindMembers): Allow the Builders of the various - members to be null. If they are skip them. This only happens - during the PInvoke declaration. - -2002-04-09 Miguel de Icaza <miguel@ximian.com> - - * parameter.cs (Parameters.ComputeParameterTypes): Flag the - failure, so we do not keep going afterwards. - - * expression.cs: (Invocation.OverloadResolve): I believe Ravi - wanted to pass `false' as the `is_delegate' argument. If this is - the case, why not use delegate_type == null to mean `is_delegate = - false' and anything else as is_delegate = true. - -Tue Apr 9 05:40:12 2002 Piers Haken <piersh@friskit.com> - - * statement.cs: fixed SimpleSwitchEmit to make 'goto case' goto the - code for the section, not the beginning of the tests. - -2002-04-08 Miguel de Icaza <miguel@ximian.com> - - * cfold.cs: Handle operator + (Enum x, Underlying x) - - * expression.cs (Binary): same. Warn about errors where we have - Enum/Enum in operator + as well. - -Mon Apr 8 06:29:03 2002 Piers Haken <piersh@friskit.com> - - * statement.cs: - - added support for switch(bool) - - optimize loading of I8/U8 constants (ldc.i4, iconv_i8) - - add TableSwitchEmit() to handle table-based switch statements - -2002-04-05 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation.OverloadResolve): Factor out code which - does parameter compatibility checking with arguments so that we can - re-use the code even from Delegate.VerifyApplicability - - (VerifyArgumentsCompat): Move above code here. - - * delegate.cs (VerifyApplicability): Get rid of duplicate code - and instead make a call to the above method. - -2002-03-31 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (attribute_type): Corresponds to System.Attribute. - We use it to keep track of classes which are attribute types. - -2002-04-02 Miguel de Icaza <miguel@ximian.com> - - * delegate.cs (Delegate.Define): Correctly define the types in the - presence of fixed and array parameters. - - * class.cs (TypeContainers.FindMembers): Use NonPublic flag while - doing FindMembers. - - * ecore.cs (Expression.MemberLookup): Reset binding flags to not - include NonPublic after the first iteration. - - * class.cs (Indexer.CheckBase): Only check if both parents are - non-null. - - * cs-parser.jay (accessor_body): If empty, set to null. - - * ecore.cs (SimpleName.SimpleNameResolve): We did not have the - same code path here to resolve constants names that we did have in - MemberAccess.DoResolve. There is too much code duplicated here. - -2002-04-01 Miguel de Icaza <miguel@ximian.com> - - * statement.cs, makefile: Drop Statementcollection and just use ArrayLists - - * ecore.cs: Optimize UserDefinedConversion by minimizing the calls - to MakeUnionSet. - - * cs-tokenizer.cs: Reuse a single StringBuilder for assembling - tokens, numbers and strings. - - * ecore.cs (MethodGroupExpr): Make Emit warn about missing - parenthesis. - - * delegate.cs: Use ComputeAndDefineParameterTypes for both the - asyncronous parameters and the regular parameters. - - * codegen.cs (CodeGen.Init): Use the constructor that allows us to - specify the target directory. - - * expression.cs: (This.DoResolve): Simplify - (As.Emit): Optimize, do not generate IsInst if the expression is - always of the given type. - - (Is.DoResolve): Bug fix, we were reporting both always/never for - the is expression. - - * (Invocation.MakeUnionSet): Simplify vastly and optimize, we were - creating too many unnecessary arrays. - -2002-03-31 Miguel de Icaza <miguel@ximian.com> - - * class.cs (EmitFieldInitializer): Use Assign expression to assign - fields instead of rolling our own initializer. Takes care of all - implicit conversions, and drops unnecessary static checks/argument. - -2002-03-31 Dick Porter <dick@ximian.com> - - * driver.cs: use the GetDirectories() return values properly, and - use "/" as path separator. - -2002-03-30 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Unary): Optimize - - expr into expr. - (Binary): Optimize a + (-b) into a -b. - - * codegen.cs (CodeGen): Made all methods static. - -2002-03-29 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs: - - * decl.cs: Rename `definition' into `TypeBuilder' and drop the - TypeBuilder property. - - * cs-parser.jay: Drop the use of RecordXXX and use RecordDecl - instead. - - * tree.cs: Removed the various RecordXXXX, and replaced with a - single RecordDecl. Removed all the accessor methods, and just - left a single access point Type - - * enum.cs: Rename DefineEnum to DefineType. - - * decl.cs: New abstract method `DefineType' used to unify the - Defines for Enumerations, Interfaces, TypeContainers and - Delegates. - - (FindType): Moved LookupInterfaceOrClass here. Moved the - LookupBaseClasses method that used to live in class.cs and - interface.cs here, and renamed to FindType. - - * delegate.cs: Implement DefineType. Take advantage of the - refactored pattern for locating the parent builder without taking - the parent_builder argument (which we know does not work if we are - nested, and triggering a toplevel definition). - -2002-03-28 Miguel de Icaza <miguel@ximian.com> - - * decl.cs (MemberCore.CheckMethodAgainstBase): Test if the - accessibility of a member has changed during override and report - an error if so. - - * class.cs (Method.Define, Property.Define): Only complain on - overrides if the method is private, any other accessibility is - fine (and since we just checked the permission is the same, we are - good to go). - - * cs-tokenizer.cs: only line, region, endregion, if, endif, else - and elif are processed always. The other pre-processing - directives are only processed if we are "taking" the path - -2002-03-29 Martin Baulig <martin@gnome.org> - - * class.cs (Method.Emit): Only emit symbolic debugging info if the - current location is not Null. - - * codegen.cs (CodeGen.SaveSymbols): Split out symbol writing code into - a separate method so we can profile it. - - * driver.cs (ShowTime): We need to use `(int) span.TotalSeconds' since - `span.Seconds' are just seconds, but no minutes or hours. - (MainDriver): Profile the CodeGen.SaveSymbols calls. - -2002-03-28 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Method.Define), (Property.Define), (Indexer.Define): - Remove the gratuitous set of Final: - - // If an interface implementation, then we can set Final. - if (((flags & MethodAttributes.Abstract) == 0) && - implementing.DeclaringType.IsInterface) - flags |= MethodAttributes.Final; - - I do not know what I was smoking when I used that. - - - * cs-parser.jay, delegate.cs: Make Delegate be a DeclSpace, first - step into fixing the name resolution issues for delegates and - unifying the toplevel name resolution. - -2002-03-28 Martin Baulig <martin@gnome.org> - - * class.cs (Method.Emit): If we have a symbol writer, call its - OpenMethod(), CloseMethod() and SetMethodSourceRange() methods to - tell it about the current method. - - * codegen.cs (EmitContext.Mark): New public method. Tell the symbol - writer that we're going to emit the first byte of IL code for a new - statement (a new source line). - (EmitContext.EmitTopBlock): If we have a symbol writer, call - EmitContext.Mark() before emitting any code. - - * location.cs (SymbolDocument): Return null when we're Null. - - * statement.cs (Statement): Moved the `Location loc' variable here. - (Statement.EmitBoolExpression): If we have a symbol writer, call - ec.Mark() before emitting any code to tell it that we're at the - beginning of a new statement. - (StatementExpression): Added `Location' argument to the constructor. - (Block): Added public readonly variable `StartLocation' and public - variable `EndLocation'. The latter is to be set using SetEndLocation(). - (Block): Added constructor which takes a start and end location. - (Block.SetEndLocation): New method. This sets the end location. - (Block.EmitMeta): If we have a symbol writer, tell it the names of the - local variables we create. - (Block.Emit): If we have a symbol writer, call ec.Mark() before emitting - each statement and do also mark the begin and end of the block. - - * cs-parser.jay (block : OPEN_BRACE): Use the new `Block' constructor to - tell it the current lexer.Location, use Location.Null for the end of the - block. - (block : OPEN_BRACE opt_statement_list CLOSE_BRACE): When closing the - current block, set its end location using SetEndLocation(). - (statement_expression): StatementExpression constructor now takes the - lexer.Location as additional argument. - (for_statement, declare_local_variables): Likewise. - (declare_local_variables): When creating a new implicit block, use the - new Block constructor and pass it the lexer.Location. - -2002-03-28 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (Expression.MemberLookup): On interfaces, lookup - members also on the parent interfaces recursively. - -2002-03-27 Miguel de Icaza <miguel@ximian.com> - - * report.cs: Use new formats, since Gonzalo finished the missing - bits. - - * expression.cs (Binary.ResolveOperator): added missing operator| - operator& and operator^ for bool/bool. - - * cs-parser.jay: CheckDef now takes a Location argument that is - used to report errors more precisly (instead of reporting the end - of a definition, we try to track something which is a lot closer - to the source of the problem). - - * cs-tokenizer.cs: Track global token use, so we can properly flag - the use of #define/#undef after the first token has been seen. - - Also, rename the reportXXXX to Error_DescriptiveName - - * decl.cs (DeclSpace.IsTopLevel): Move property here from - TypeContainer, so that Enum and Interface can use this too. - - * class.cs (TypeContainer.LookupInterfaceOrClass, - GetInterfaceOrClass, GetClassBases, DefineType): Drop the - `builder' argument. Typically this was used to pass the parent - builder (a ModuleBuilder or a TypeBuilder from whoever triggered - the definition). - - The problem is that a nested class could trigger the definition of - a toplevel class, and the builder would be obviously wrong in that - case. - - So we drop this argument, and we compute dynamically the - TypeBuilder/ModuleBuilder (the correct information was available - to us anyways from DeclSpace.Parent) - - * interface.cs (Interface.DefineInterface): Drop builder - parameter cleanup like class.cs - - * enum.cs (Enum.DefineEnum): Drop builder parameter. Clean up - like class.cs - - * statement.cs (Switch.EmitObjectInteger): Emit short/ushort - values. - - (Try.Emit): Propagate the returns value from the statement. - - (Return.Emit): Even if we are leavning - - * driver.cs: Catch IOExpcetion for Directory.GetFiles as well. - - * modifiers.cs: Fix the computation of MethodAttributes flags. - -Tue Mar 26 21:14:36 CET 2002 Paolo Molaro <lupus@ximian.com> - - * driver.cs: allow compilation of files that start with '/'. - Add a default case when checking the argument of --target. - -2002-03-25 Miguel de Icaza <miguel@ximian.com> - - * interface.cs: Implement the same search algorithm for types in - the interface code. - - * delegate.cs: Do not allow multiple definition. - - * Recovered ChangeLog that got accidentally amputated - - * interface.cs (Interface.DefineInterface): Prevent from double definitions. - - * rootcontext.cs: Load manually enum to allow core classes to - contain enumerations. - - * enum.cs, ecore.cs, driver.cs, attribute.cs, class.cs, expression.cs: - Update to new static methods in TypeManager. - - * typemanager.cs (GetMethod, GetConstructor): Use our - implementation of FindMembers to find the members, since during - corlib compilation, the types are TypeBuilders and GetMethod and - GetConstructor do not work. - - Make all methods in TypeManager static. - - (InitCodeHelpers): Split the functionality from - the InitCodeTypes function. - - * driver.cs: Call InitCodeHelpers after we have populated the - types. - - * cs-parser.jay (delegate_declaration): we did not used to compute - the delegate name correctly for void delegates. - -2002-03-24 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs (RootContext): Init the interface_resolve_order - and type_container_resolve_order always. - - (ResolveCore, BootstrapCorlib_ResolveClass, - BootstrapCorlib_ResolveStruct): New functions to bootstrap the - compiler when compiling with --nostdlib - - * class.cs (TypeContainer.DefineType): Check that our parent is - not null. This test is most important when we are bootstraping - the core types. - - * codegen.cs: Split out the symbol writing code. - -2002-03-25 Martin Baulig <martin@gnome.org> - - * driver.cs (-g): Made -g an alias for --debug. - -2002-03-24 Martin Baulig <martin@gnome.org> - - * codegen.cs (SymbolWriter): New public variable. Returns the - current symbol writer. - (CodeGen): Added `bool want_debugging_support' argument to the - constructor. If true, tell the ModuleBuild that we want debugging - support and ask it for the ISymbolWriter. - (Save): If we have a symbol writer, call it's Close() method after - saving the assembly. - - * driver.c (--debug): New command line argument to create a - debugger information file. - - * location.cs (SymbolDocument): New public property. Returns an - ISymbolDocumentWriter object for the current source file or null - if we don't have a symbol writer. - -2002-03-21 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (LoadAssembly): Correctly return when all the paths - have been tried and not before. - - * statement.cs (Switch.Emit): return the actual coverage for this - statement (returns/not-returns) - - (Switch.SimpleSwitchEmit): Do not generate jumps to the end of the - switch of the statement if we are the last switch section. That - kills two problems: try/catch problems (we used to emit an empty - nop at the end) and switch statements where all branches would - return. - -2002-03-19 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Add default assemblies (the equivalent to the - Microsoft CSC.RSP file) - - * cs-tokenizer.cs: When updating `cols and setting it to zero, - also update tokens_seen and set it to false. - - * driver.cs: Implement --recurse for Mike. - - * driver.cs (SplitPathAndPattern): Small bug fix, I was not - correctly splitting out the paths. - -2002-03-18 Miguel de Icaza <miguel@ximian.com> - - * interface.cs (Interface.PopulateProperty): Instead of using - `parent' as the declaration space for the set parameters, use - `this' - - * support.cs (InternalParameters): InternalParameters constructor - takes a DeclSpace instead of a TypeContainer. - - * expression.cs (ArrayCreation.EmitDynamicInitializers): If value - types are being initialized, load the address of it before calling - the function. - - (New): Provide a mechanism to disable the generation of local - value type temporaries when the caller will be providing us with - an address to store it. - - (ArrayCreation.EmitDynamicInitializers): Use it. - -2002-03-17 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Invocation.EmitArguments): Only probe for array - property if there is more than one argument. Sorry about that. - - * class.cs (Invocation.EmitArguments): Fix to emit arguments for - empty param arrays. - - * class.cs (Method.LabelParameters): Fix incorrect code path that - prevented the `ParamArrayAttribute' from being applied to the - params attribute. - -2002-03-16 Miguel de Icaza <miguel@ximian.com> - - * support.cs (ReflectionParameters): Correctly compute whether the - last argument is a params array. Fixes the problem with - string.Split ('a') - - * typemanager.cs: Make the assemblies array always be non-null - (empty, but non-null) - - * tree.cs (RecordDecl): New function that abstracts the recording - of names. This reports error 101, and provides a pointer to the - previous declaration. Fixes a crash in the compiler. - - * cs-parser.jay (constructor_declaration): Update to new grammar, - and provide a constructor_body that can be empty. - -2002-03-15 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Add support for --resources. - - * expression.cs: (FetchGetMethod, FetchAddressMethod, EmitAssign): - Make all types for the various array helper methods be integer. - - * ecore.cs (Expression.ConvertNumericExplicit): Pass the - CheckState to ConvCast. - - (ConvCast): Now it takes a `checked' state argument, to avoid - depending on the emit context for the conversion, and just using - the resolve time setting. - - * expression.cs (ArrayCreation.EmitArrayArguments): New function, - instead of Invocation.EmitArguments. We do not emit the original - arguments, instead we emit those which have been converted to - unsigned int expressions. - - * statement.cs (Block.EmitMeta): Drop tracking of indexes. - - * codegen.cs: ditto. - - * expression.cs (LocalVariableReference): Drop the use of the - Store function that depended on the variable index. - - * statement.cs (VariableInfo): Drop the `Idx' property from this - class, as this is not taking into account the indexes for - temporaries tat we generate during the execution, getting the - indexes wrong. - - * class.cs: First emit class initializers, then call the parent - constructor. - - * expression.cs (Binary): Fix opcode emision. - (UnaryMutator.EmitCode): Support checked code generation - - * ecore.cs (MemberLookup): TypeManager.FindMembers will return - matches for events for both the Static and Instance scans, - pointing to the same element. Fix that. - -2002-03-14 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs (ResolveTree): Always set the - interface_resolve_order, because nested interfaces will be calling - into us. - - * class.cs (GetInterfaceOrClass): Track the same resolution - process used by TypeManager.LookupType. This fixes the nested - type lookups in class declarations (separate path from - LookupType). - - (TypeContainer.DefineType): Also define nested interfaces. - (TypeContainer.RegisterOrder): New public function used to - register the order in which child interfaces need to be closed. - - Nested interfaces need to be closed after their parents have been - created. - - * interface.cs (InterfaceAttr): Put all the logic for computing - the interface attribute here. - - (DefineInterface): Register our interface order with the - RootContext or with the TypeContainer depending on the case. - -2002-03-12 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: rework foreach statement to work with the new - changes to the policy on SimpleNames. - - * report.cs: support Stacktrace on warnings as well. - - * makefile: drop --unsafe and /unsafe from the compile. - -2002-03-13 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (StandardConversionExists): Modify to take an Expression - as the first parameter. Ensure we do null -> reference type conversion - checking. - - * Everywhere : update calls accordingly, making use of MyEmptyExpr to store - temporary Expression objects. - -Wed Mar 13 12:32:40 CET 2002 Paolo Molaro <lupus@ximian.com> - - * interface.cs: workaround bug in method overloading resolution - (there is already a bugzilla bug for it). - -2002-03-12 Miguel de Icaza <miguel@ximian.com> - - We could also solve this problem by having a separate path for - performing type lookups, instead of DoResolve, we could have a - ResolveType entry point, and only participating pieces of the - production (simplename, deref, array) would implement this. - - * codegen.cs (EmitContext): New field OnlyLookupTypes used to - signal SimpleName to only resolve type names and not attempt to - resolve anything else. - - * expression.cs (Cast): Set the flag. - - * ecore.cs (SimpleName): Use the OnlyLookupTypes flag - - * class.cs: Only report 108 if there is no `new' modifier. - - * cs-parser.jay: rework foreach statement to work with the new - changes to the policy on SimpleNames. - - * report.cs: support Stacktrace on warnings as well. - - * makefile: drop --unsafe and /unsafe from the compile. - -2002-03-11 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable - lookups here, instead of doing that at parse time. This means - that our grammar will not introduce `LocalVariableReferences' as - expressions at this point. That solves the problem of code like - this: - - class X { - static void Main () - { int X = 1; - { X x = null }}} - - This is only half the fix. The full fix requires parameters to - also be handled in this way. - - * Everywhere: Use ec.DeclSpace on calls to LookupType, as this - makes the use more obvious of the DeclSpace. The - ec.TypeContainer.TypeBuilder is now only used to pull the - TypeBuilder for it. - - My theory is that I can get rid of the TypeBuilder completely from - the EmitContext, and have typecasts where it is used (from - DeclSpace to where it matters). - - The only pending problem is that the code that implements Aliases - is on TypeContainer, and probably should go in DeclSpace. - - * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable - lookups here, instead of doing that at parse time. This means - that our grammar will not introduce `LocalVariableReferences' as - expressions at this point. That solves the problem of code like - this: - - class X { - static void Main () - { int X = 1; - { X x = null }}} - - This is only half the fix. The full fix requires parameters to - also be handled in this way. - - * class.cs (Property.DefineMethod): When implementing an interface - method, set newslot, when implementing an abstract method, do not - set the flag (before we tried never setting it, or always setting - it, which is the difference). - (Indexer.DefineMethod): same. - (Method.DefineMethod): same. - - * ecore.cs: Only set the status used flag if we get back a Field. - - * attribute.cs: Temporary hack, so Paolo can keep working. - -2002-03-08 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (Attribute.UnmanagedType): This is to keep track of - the unmanaged type in the case we have a MarshalAs attribute. - - (Resolve): Handle the case when we are parsing the special MarshalAs - attribute [we need to store the unmanaged type to use later] - - * typemanager.cs (marshal_as_attr_type): Built in type for the - MarshalAs Attribute. - - * attribute.cs (ApplyAttributes): Recognize the MarshalAs attribute - on parameters and accordingly set the marshalling info. - -2002-03-09 Miguel de Icaza <miguel@ximian.com> - - * class.cs: Optimizing slightly by removing redundant code after - we switched to the `NoTypes' return value. - (Property.DefineMethod): use NoTypes here too. - - This fixes the bug I introduced in my last batch of changes. - -2002-03-05 Ravi Pratap <ravi@ximian.com> - - * tree.cs (RecordEnum): Add. We now keep track of enums too. - - * class.cs (LookupInterfaceOrClass): Check against the list of recorded - Enums since those are types too. - - * cs-parser.jay (enum_declaration): Record enums as we parse them. - - * enum.cs (DefineEnum): Return if the TypeBuilder has already been defined - thanks to a call during the lookup process. - -2002-03-07 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Foreach): Lots of work to accomodate a particular - kind of foreach statement that I had not kept in mind. It is - possible to have foreachs on classes that provide a GetEnumerator - method that return objects that implement the "pattern" for using - a foreach, there is no need to support GetEnumerator - specifically. - - This is needed to compile nant. - - * decl.cs: Only report 114 if the member is not `Finalize' and if - the warning level is at least 2. - - * class.cs: Moved the compare function from Method to - MethodSignature. - - (MethodSignature.InheritableMemberSignatureCompare): Add new - filter function that is used to extract inheritable methods from a - class. - - (Method.Define): Use the new `inheritable_method_signature_filter' - delegate - - * cs-tokenizer.cs (get_cmd_arg): Do not add white space to the - command. - -2002-03-06 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (Expression.ConvertReferenceExplicit): Removed dead code. - - * cs-parser.jay: Add opt_semicolon to the interface declaration. - - * expression.cs: Pass location information to - ConvertImplicitStandard. - - * class.cs: Added debugging code to track return values from - interfaces. - -2002-03-05 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Is.DoResolve): If either side of the `is' is an - interface, do not flag the warning. - - * ecore.cs (ImplicitReferenceConversion): We need a separate test - for interfaces - - * report.cs: Allow for --fatal to be used with --probe. - - * typemanager.cs (NoTypes): Move the definition for the empty Type - array here. - - * class.cs (TypeContainer.FindMembers): Also look for methods defined by - properties. - (TypeContainer.DefineProxy): New function used to proxy to parent - implementations when implementing interfaces. - (TypeContainer.ParentImplements): used to lookup if our parent - implements a public function that is required by an interface. - (TypeContainer.VerifyPendingMethods): Hook this up. - - * typemanager.cs (TypeManager, AddModule, AddAssembly): Make the - `modules' and `assemblies' arraylists into arrays. We only grow - these are the very early start up of the program, so this improves - the speedof LookupType (nicely measured). - - * expression.cs (MakeByteBlob): Replaced unsafe code with - BitConverter, as suggested by Paolo. - - * cfold.cs (ConstantFold.Binary): Special case: perform constant - folding of string concatenation, but if either side is a string, - and the other is not, then return null, and let the runtime use - the concatenation on the string plus the object (using - `Object.ToString'). - -2002-03-04 Miguel de Icaza <miguel@ximian.com> - - Constant Folding has been implemented now. - - * expression.cs (Unary.Reduce): Do not throw an exception, catch - the error instead on types that are not supported in one's - complement. - - * constant.cs (Constant and all children): New set of functions to - perform implict and explicit conversions. - - * ecore.cs (EnumConstant): Implement the new functions to perform - conversion by proxying to the child expression. - - * codegen.cs: (ConstantCheckState): Constant evaluation has its - own separate setting that can not be turned off from the command - line using --unchecked or --checked and is only controlled using - the checked/unchecked statements and expressions. This setting is - used by the constant folder to flag errors. - - * expression.cs (CheckedExpr, UncheckedExpr): Set the - ConstantCheckState as well. - - During Resolve, they also have to flag the state, because the - constant folder runs completely in the Resolve phase. - - * statement.cs (Checked, Unchecked): Set the ConstantCheckState as - well. - -2002-03-01 Miguel de Icaza <miguel@ximian.com> - - * cfold.cs: New file, this file contains the constant folder. - - * ecore.cs (IMemoryLocation.AddressOf): Now takes an extra - argument to track whether we are using the resulting address to - load or store a value and provide better error messages. - - (FieldExpr.Emit, FieldExpr.EmitAssign, FieldExpr.AddressOf): Use - new AddressOf arguments. - - * statement.cs (Foreach.EmitCollectionForeach): Update - - * expression.cs (Argument.Emit): Call AddressOf with proper - arguments to track usage. - - (New.DoEmit): Call AddressOf with new arguments. - - (Unary.Emit): Adjust AddressOf call. - -2002-03-01 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (member_access): Change the case for pre-defined types - to use a MemberAccess instead of a SimpleName. Thanks to Felix again for - this suggestion. - - * class.cs (Operator::Emit): If we are abstract or extern, we don't have - a method body. - - * attribute.cs (CheckAttribute, ApplyAttribute): Ensure that we treat operators - essentially like methods and apply attributes like MethodImplOptions to them too. - - * ecore.cs (SimpleName.SimpleNameResolve): Perform a check on ec.TypeContainer.TypeBuilder - not being null. - - * codegen.cs (EmitContext): The constructor now takes in an extra argument specifying the - DeclSpace as the distinction is important. We provide sane defaults as usually the TypeContainer - is the DeclSpace. - - * Update code everywhere accordingly. - - * ecore.cs : Change references to ec.TypeContainer to ec.DeclSpace where appropriate. - - * cs-parser.jay (enum_declaration): Set the current namespace of the enum. - -2002-02-28 Ravi Pratap <ravi@ximian.com> - - * rootcontext.cs (LookupType): As we cycle through the chain of namespaces - try performing lookups against those instead of jumping straight into using - the 'using' clauses. - - (ImplicitParent): Add. Thanks to Felix Arrese-Igor for this idea. - - (LookupType): Perform lookups in implicit parents too. - - * class.cs (GetInterfaceOrClass): Modify to perform the exact same lookup - sequence as RootContext.LookupType. - - * rootcontext.cs (NamespaceLookup): Split out code from LookupType which tries - the various cases of namespace lookups into this method. - -2002-03-01 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Add support for [Attribute ()] (empty arguments - in positional arguments) - - * class.cs (Operator): Update the AllowedModifiers to contain - extern. - - * cs-parser.jay: Update operator declaration to allow for the - operator body to be empty. - - * cs-tokenizer.cs: Added '\u' unicode support in strings and hex - values. - -2002-02-27 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Method.Emit): Label parameters. - - * driver.cs: Return 1 or 0 as the program exit code. - -2002-02-26 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Special case the `null' object when trying to - auto-compute the type, as anything can be explicitly converted to - that. - - * ecore.cs (Expression.ConvertExplicit): Bug fix, thanks for - spotting this Paolo. - - (Expression.ImplicitNumericConversion): Perform comparissions of - the type using the underlying type in the case of an enumeration - rather than using the enumeration type for the compare. - - Cope with the underlying == type case, which is not possible to - catch before. - - (Expression.ConvertNumericExplicit): Perform comparissions of - the type using the underlying type in the case of an enumeration - rather than using the enumeration type for the compare. - - * driver.cs: If the user does not supply an extension, assume .exe - - * cs-parser.jay (if_statement): Rewrote so that we can track the - location for the if statement. - - * expression.cs (Binary.ConstantFold): Only concat strings when - the operation is "+", not everything ;-) - - * statement.cs (Statement.EmitBoolExpression): Take a location - argument. - (If, While, Do): Track location. - - * expression.cs (Binary.ResolveOperator): In the object + string - case, I was missing a call to ConvertImplicit - -2002-02-25 Ravi Pratap <ravi@ximian.com> - - * parameter.cs (Parameter.ExternalType): Take in extra DeclSpace and - Location arguments. Ensure we use RootContext.LookupType to do our work - and not try to do a direct Type.GetType and ModuleBuilder.GetType - - * interface.cs (PopulateMethod): Handle the type of the parameter being - null gracefully. - - * expression.cs (Invocation.BetterFunction): Handle the case when we - have a params method with no fixed arguments and a call is made with no - arguments. - -2002-02-25 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Add support for the quote-escape-sequence in - the verbatim-string-literal - - * support.cs (InternalParameters.ParameterModifier): handle null - fixed parameters. - (InternalParameters.ParameterType): ditto. - - * parameter.cs (VerifyArgs): Also check if the fixed parameter is - duplicating the name of the variable parameter. - (GetParameterByName): Fix bug where we were not looking up array - paramters if they were the only present (thanks Paolo!). - (GetParameterInfo): We only have an empty set of types if both - fixed and array are set to null. - (GetParameterInfo-idx): Handle FixedParameter == null - - * cs-parser.jay: Handle the case where there is no catch - statements (missing null test). - -2002-02-22 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (MainDriver): Be conservative on our command line - handling. - - Catch DirectoryNotFoundException when calling GetFiles. - - (SplitPathAndPattern): Used to split the input specification into - a path and a pattern that we can feed to Directory.GetFiles. - -2002-02-21 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Fixed): Implement the last case of the Fixed - statement (string handling). - - * expression.cs (StringPtr): New class used to return a char * to - a string; Used by the Fixed statement. - - * typemanager.cs: Add char_ptr_type. Add get_OffsetToStringData method. - - * expression.cs (Binary.ResolveOperator): Remove redundant - MemberLookup pn parent type. - Optimize union call, we do not need a union if the types are the same. - (Unary.ResolveOperator): REmove redundant MemberLookup on parent - type. - - Specialize the use of MemberLookup everywhere, instead of using - the default settings. - - (StackAlloc): Implement stackalloc keyword. - - * cs-parser.jay: Add rule to parse stackalloc. - - * driver.cs: Handle /h, /help, /? - - * expression.cs (MakeByteBlob): Removed the hacks we had in place - before we supported unsafe code. - - * makefile: add --unsafe to the self compilation of mcs. - -2002-02-20 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (PointerArithmetic): New class that is used to - perform pointer arithmetic. - (Binary.Resolve): Handle pointer arithmetic - Handle pointer comparission. - (ArrayPtr): Utility expression class that is used to take the - address of an array. - - (ElementAccess): Implement array access for pointers - - * statement.cs (Fixed): Implement fixed statement for arrays, we - are missing one more case before we are done. - - * expression.cs (Indirection): Implement EmitAssign and set the - ExprClass to Variable. This allows pointer dereferences to be - treated as variables, and to have values assigned to them. - - * ecore.cs (Expression.StoreFromPtr): New utility function to - store values dereferencing. - -2002-02-20 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Binary.ResolveOperator): Ensure that we are - not trying to operate on a void type - this fixes the reported - bug. - - * decl.cs (CheckMethodAgainstBase): Do not allow overriding if - the parent implementation is sealed. - - * ../errors/cs0239.cs : Add. - - * attribute.cs (ApplyAttributes): Handle Modulebuilders too. - - * typemanager.cs (unverifiable_code_type): Corresponds to - System.Security.UnverifiableCodeAttribute. We need to emit this for modules - which have unsafe code in them. - - * rootcontext.cs (EmitCode): Emit the above attribute when we are in an - unsafe context. - -2002-02-19 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Add support for @"litreal strings" - - Make tokenizer accept pre-processor directives - on any column (remove the old C-like limitation). - - * rootcontext.cs (EmitCode): Emit any global attributes. - (AddGlobalAttributes): Used to keep track of assembly attributes. - - * attribute.cs (ApplyAttributes): Support AssemblyAttributes. - - * cs-parser.jay: Add support for global attributes. - -2002-02-17 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Indirection): New helper class. Unary will - create Indirection classes to be able to implement the - IMemoryLocation interface on it. - -2002-02-16 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay (fixed_statement): reference the right statement. - - * statement.cs (Fixed.Emit): Finish implementing the fixed - statement for the &x case. - -2002-02-14 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Property.Define, Method.Define): Remove newslot when - `implementing'. - - * modifiers.cs: My use of NewSlot when `Abstract' was set was - wrong. NewSlot should only be used if the `new' keyword is present. - - * driver.cs (GetSystemDir): Use CodeBase instead of FullName for - locating our system dir. Sorry about this. - -2002-02-13 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (GetSystemDir): Compute correctly the location of our - system assemblies. I was using the compiler directory instead of - the library directory. - -2002-02-13 Ravi Pratap <ravi@ximian.com> - - * expression.cs (BetterFunction): Put back in what Miguel commented out - since it is the correct fix. The problem is elsewhere ;-) - - (IsParamsMethodApplicable): Fix bug where we were not checking that the fixed - parameters of the parms method are themselves compatible or not ! - - (StandardConversionExists): Fix very dangerous bug where we were forgetting - to check that a class implements an interface before saying that an implicit - conversion was allowed. Use ImplementsInterface to do the checking. - -2002-02-13 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Method.Define): Track whether we are an explicit - implementation or not. And only call DefineMethodOverride if we - are an explicit implementation. - - (Property.DefineMethod): Ditto. - -2002-02-11 Ravi Pratap <ravi@ximian.com> - - * expression.cs (BetterFunction): Catch hideous bug which was - preventing us from detecting ambiguous calls due to implicit casts i.e - cs0121. - -2002-01-29 Miguel de Icaza <miguel@ximian.com> - - * support.cs (Pair): Remove un-needed method. I figured why I was - getting the error in cs-parser.jay, the variable in a foreach loop - is readonly, and the compiler does not really treat this as a variable. - - * cs-parser.jay (fixed_statement): Fix grammar. Use ASSIGN - instead of EQUALS in grammar. - - * typemanager.cs (VerifyUnmanaged): Report correct error (208) - - * expression.cs (Unary.DoResolve): Check whether the argument is - managed or not. - -2002-01-28 Miguel de Icaza <miguel@ximian.com> - - * support.cs: Api for Pair to set a value. Despite the fact that - the variables are public the MS C# compiler refuses to compile - code that accesses the field if the variable is part of a foreach - statement. - - * statement.cs (Fixed): Begin implementation of the fixed - statement. - - (Block.AddVariable): Return the VariableInfo on success and null - on failure instead of true/false. - - * cs-parser.jay (foreach): Catch errors on variables already - defined (we were ignoring this value before) and properly unwind - the block hierarchy - - (fixed_statement): grammar for the fixed statement. - -2002-01-25 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (UnaryMutator.IsIncrementableNumber): Allow also - pointer types to be incretemented. - - (SizeOf): Implement. - - * cs-parser.jay (pointer_member_access): Implement - expr->IDENTIFIER production. - - * expression.cs (IndexerAccess.DoResolve, ArrayAccess.DoResolve, - MemberAccess.DoResolve, Invocation.DoResolve): Check for pointers - on safe contexts. - - (Unary): Implement indirection. - - * ecore.cs (Expression.UnsafeError): Reports error 214 (pointer - use in non-unsafe context). - - (SimpleName.DoResolve): Check for pointers in field access on safe - contexts. - - (Expression.LoadFromPtr): Factor the load-indirect code in this - function. This was duplicated in UnboxCast and ParameterReference - -2002-01-24 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ComposedCast): report an error if a pointer cast - is used in a safe region. - - * ecore.cs (Expression.ConvertExplicit): Add rules for implicit - pointer type casts in unsafe context. - - * codegen.cs (EmitContext): Set up IsUnsafe. - - * cs-parser.jay (non_expression_type): Add productions for pointer - casts. - - * expression.cs (Invocation.EmitCall): Remove chunk of buggy - code. We should not use force into static mode if the method is - not virtual. Fixes bug in MIS - - * statement.cs (Do.Emit, While.Emit, For.Emit, - Statement.EmitBoolExpression): Add support to Do and While to - propagate infinite loop as `I do return' semantics. - - Improve the For case to also test for boolean constants. - - * attribute.cs (Attribute.ApplyAttributes): Add ParameterBuilder - to the list of attributes we can add. - - Remove `EmitContext' argument. - - * class.cs (Method.Define): Apply parameter attributes. - (Constructor.Define): Apply parameter attributes. - (MethodCore.LabelParameters): Move here the core of labeling - parameters. - - * support.cs (ReflectionParameters.ParameterModifier, - InternalParameters.ParameterModifier): Use IsByRef on the type and - only return the OUT bit for these parameters instead of in/out/ref - flags. - - This is because I miss-understood things. The ParameterInfo.IsIn - and IsOut represent whether the parameter has the [In] and [Out] - attributes set. - -2002-01-22 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (FieldExpr.Emit): Release temporaries. - - * assign.cs (LocalTemporary.Release): new function. - - * codegen.cs (EmitContext.GetTemporaryStorage, - EmitContext.FreeTemporaryStorage): Rework the way we deal with - temporary storage. Now we can "put back" localbuilders when we - are done with them - -2002-01-21 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (FieldExpr.Emit): Handle initonly fields specially: we - need to make a copy of the variable to generate verifiable code. - -2002-01-19 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Compute dynamically the system directory. - - * ecore.cs (CopyNewMethods): reworked, exposed, made public. - Slower, but more generally useful. Used by the abstract - registering implementation. - - * expression.cs (ResolveMemberAccess): Reorder the way we evaluate - the rules for the special rule on Type/instances. First check if - we have the same name, and if so, try that special static path - rather than the instance path. - -2002-01-18 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Emit 642 (warning: possible empty statement) for - for, while and if. - - * class.cs (TypeBuilder.DefineType): Do not allow inheritance from - Enum, ValueType, Delegate or Array for non-corlib compiles. - - * cs-tokenizer.cs: Catch long identifiers (645) - - * typemanager.cs (IndexerPropetyName): Ravi never tested this - piece of code. - - * class.cs (TypeContainer.RegisterRequiredImplementations): Bug - fix, we were returning too early, so we were not registering - pending methods from abstract classes. - - Do not register pending methods if the class is abstract. - - * expression.cs (Conditional.DoResolve): Report circular implicit - conversions when we neecd to compute it for conditional - expressions. - - (Is.DoResolve): If the expression is always of the provided type, - flag warning 183. If the expression can not ever be of the - provided type flag warning 184. - - * class.cs: Catch 169 as well. - - * ecore.cs (FieldExpr): For now in AddressOf mark as assigned and - read. - -2002-01-18 Nick Drochak <ndrochak@gol.com> - - * makefile: remove path to beta2 csc.exe. path to csc.exe must be in PATH instead. - -2002-01-17 Miguel de Icaza <miguel@ximian.com> - - * interface.cs: (PopulateMethod): Check for pointers being defined - only if the unsafe context is active. - (PopulateProperty): ditto. - (PopulateIndexer): ditto. - - * class.cs (Method, Method.Define): Allow `unsafe' modifier to be - specified. If pointers are present, make sure that they are - present in an unsafe context. - (Constructor, Constructor.Define): ditto. - (Field, Field.Define): ditto. - (Property, Property.Define): ditto. - (Event, Event.Define): ditto. - - * interface.cs (Interface.GetInterfaceTypeByName): Only lookup the - hashtable if there are classes or structs defined. - - * expression.cs (LocalVariableReference.DoResolve): Simplify this - code, as the constant resolution moved. - - * statement.cs (Block.EmitMeta): Resolve all constants as we emit - the metadata, so we can flag error 133. - - * decl.cs (MemberCore.UnsafeOK): New function to test that a - pointer is being declared in an unsafe context. - -2002-01-16 Miguel de Icaza <miguel@ximian.com> - - * modifiers.cs (Modifiers.Check): Require a Location argument. - Report error 227 for Unsafe use. - - * typemanager.cs: Remove IsPointerType, we should be using Type.IsPointer - - * statement.cs (For.Emit): If the test is null, then report that - we do `return', as we wont reach anything afterwards. - - (Switch.SwitchGoverningType): Track the expression that matched - the conversion. - - * driver.cs: Allow negative numbers as an error code to flag. - - * cs-parser.jay: Handle 1551. - - * namespace.cs: Add 1537 checking (repeated using alias namespaces). - -2002-01-15 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Report 1518 (type declaration can only contain - class, struct, interface, enum or delegate) - - (switch_label): Report 1523 (keywords `case' or `default' must - preced code) - - (opt_switch_sections): Report 1522 (empty switch) - - * driver.cs: Report 1515 (response file specified multiple times) - Report 1516 (Source file specified multiple times). - - * expression.cs (Argument.Resolve): Signal 1510 - - (BaseAccess.Resolve, BaseIndexer.Resolve): Signal 1511 (base - access not allowed in static code) - -2002-01-11 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (IsPointerType): Utility method which we are going - to need a lot. - - * ecore.cs (ImplicitReferenceConversion): A pointer type cannot be cast to - the object type, so we take care of that. - - * expression.cs (FullMethodDesc): Also include the return type in descriptions. - - * support.cs (ParameterDesc): Fix minor bug which was causing params tags to be - added to non-params parameters :-) - - * typemanager.cs (CSharpName): Include 'void' type too. - - (void_ptr_type): Include in the set of core types. - - * ecore.cs (ConvertImplicit): Make use of ConvertImplicitStandard instead of - duplicating code. - - (ConvertImplicitStandard): Handle standard implicit pointer conversions when we have - an unsafe context. - - * cs-parser.jay (local_variable_pointer_type): Add support for 'void *' as I had - completely forgotten about it. - -2002-01-10 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (pointer_type): Add. This begins our implementation - of parsing rules for unsafe code. - - (unsafe_statement): Implement. - - (embedded_statement): Modify to include the above. - - * statement.cs (Unsafe): Implement new class for unsafe blocks. - - * codegen.cs (EmitContext.InUnsafe): Add. This determines - if the current context is an unsafe one. - - * cs-parser.jay (local_variable_pointer_type): Since local variable types - are handled differently, we need separate rules for them. - - (local_variable_declaration): Update to use local_variable_pointer_type - to allow variable declarations of unmanaged pointer types. - - * expression.cs (Unary.ResolveOperator): Ensure that the '&' operator is used only - in unsafe contexts. - - * ../errors/cs0214.cs : Add. - -2002-01-16 Nick Drochak <ndrochak@gol.com> - - * makefile: remove 'response' file when cleaning. - -2002-01-15 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Report 1524. - -2002-01-14 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (RegisterMethod): drop checking if we have - registered this from here - -2002-01-12 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Method.EmitDestructor): Implement calling our base - destructor. - - * statement.cs (Try.Emit): Fix to reset the InFinally to the old - value of InFinally. - - * codegen.cs (EmitContext.EmitTopBlock): Destructors will call - this routine and will wrap the call in a try/catch block. Deal - with the case. - -2002-01-11 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (Expression.MemberLookup): instead of taking a - parameter `same_type' that was used to tell whether we could - access private members we compute our containing type from the - EmitContext. - - (FieldExpr): Added partial support for volatile fields. This does - not work for volatile fields exposed from assemblies, as I can not - figure out how to extract the modreq from it. - - Updated all the source files to use this. - - * codegen.cs (EmitContext): Compute ContainerType ahead of time, - because it is referenced by MemberLookup very often. - -2002-01-09 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (IndexerPropertyName): If we have a TypeBuilder, use - TypeBuilder.GetCustomAttributes to retrieve what we need. - - Get rid of redundant default_member_attr_type as this is the same as - default_member_type which already exists. - - * interface.cs, attribute.cs : Update accordingly. - -2002-01-08 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs: Enable IndexerPropertyName again. It does not - work for TYpeBuilders though. Ravi, can you please fix this? - - * cs-tokenizer.cs: Accept _ as a name in pp-expressions. - - * expression.cs (Argument.Emit): Handle the case of ref objects - being passed to ref functions; - - (ParameterReference.EmitLoad): Loads the content of the pointer - without dereferencing. - -2002-01-07 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Implemented the pre-processing expressions. - -2002-01-08 Ravi Pratap <ravi@ximian.com> - - * class.cs (Indexer.DefineMethod): Incorporate the interface - type in the name of the method if we are doing explicit interface - implementation. - - * expression.cs (ConversionExists): Remove as it is completely obsolete. - - (BetterConversion): Fix extremely trivial bug where we were referring to - ConversionExists instead of StandardConversionExists ! Hooray, things are fine - again ! - - * ../errors/bug16.cs : Add although we have fixed it. - -2002-01-07 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (BaseIndexer): Begin implementation. - - * class.cs (TypeContainer.IsInterfaceMethod): Bug fix. - - * cs-parser.jay (indexer_declarator): Use qualified_identifier - production directly to remove a shift/reduce, and implement - explicit interface implementation. - - * cs-tokenizer.cs: Fix tokenizer, it was consuming one extra char - after a floating point suffix. - - * expression.cs (DoNumericPromotions): Improved the conversion for - uint/uint. If we have a constant, we avoid doing a typecast to a - larger type. - - * class.cs (Indexer): Implement explicit interface implementation - for indexers. - -Sat Jan 5 16:08:23 CET 2002 Paolo Molaro <lupus@ximian.com> - - * class.cs: make the default instance constructor public and hidebysig. - -2001-01-03 Ravi Pratap <ravi@ximian.com> - - * interface.cs (EmitDefaultMemberAttr): Make this helper method static - so we can call it from elsewhere. - - * class.cs (TypeContainer.Emit): Emit the attribute here too. The rule is that - we emit it internally if the class has a defined indexer; otherwise the user - emits it by decorating the class definition with the DefaultMemberAttribute. - - * attribute.cs (ApplyAttributes): Perform checks to see that the DefaultMember - attribute is not used on a type which defines an indexer. - - * cs-tokenizer.cs (get_cmd_arg): Ensure we trim whitespace and also include the tab - character when we skip whitespace. - - * ../errors/cs0646.cs : Add. - -2002-01-03 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (SimpleName.ResolveSimpleName): Report error 120 - again. - - * makefile: Add practical target `mcs3.exe' which builds the third - generation compiler. - - * expression.cs (New): Fix structures constructor calling. - - * class.cs (Property, Method, Indexer): Emit Final flag on the - method if we are an interface implementation and we are not - abstract. - - * ecore.cs (PropertyExpr): New public field `IsBase', tells - whether this property is referencing a `base' method. - - * expression.cs (Invocation.EmitCall): take an extra argument: - is_base, this is used to determine whether the `call' or - `callvirt' opcode should be used. - - - * delegate.cs: update EmitCall. - - * class.cs (Method.Define): Set NewSlot for the cases where we are - not implementing an interface method. - - (Property.Define): ditto. - -2002-01-02 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: (Tokenizer.escape): Escape '\r' as '\r' not as - 'r'. Allows mcs to parse itself fully. - -2002-01-02 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation.num_automatic_initializers): Keep track - of the number of initializers that require the InitializeArray method. - - (CheckIndices): Store the Expression in all cases - not the plain value. Also - update the above field where necessary. - - (MakeByteBlob): Update accordingly. - - (DoEmit): Call EmitStaticInitializers only if the number of initializers is - greater than 2. - - (EmitDynamicInitializers): Update in accordance with the new optimization. - - (ArrayAccess.EmitStoreOpcode): Include char type along with short and ushort - the - same OpCode applies. - - * cs-parser.jay : Fix some glaring errors I introduced. - -2002-01-01 Ravi Pratap <ravi@ximian.com> - - * parameters.cs (AddVariable, AddConstant): Pass in current_local_parameters - so that we can check for name clashes there too. - - * typemanager.cs (default_member_attr_type): The attribute that we need to emit - for interface indexers. - - * interfaces.cs (Define): Emit the default member attribute. - - * expression.cs (MakeByteBlob): Fix extremely trivial bug where the wrong - variable was being referred to while setting the value ;-) - -2002-01-01 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (MakeByteBlob): Optimize: we do not need to fill - byte-by-byte information when we know the data is zero. - - Make the block always a multiple of 4, because - DefineInitializedData has a bug. - - * assign.cs: Fix, we should assign from the temporary, not from - the source. - - * expression.cs (MakeByteBlob): Fix my incorrect code. - -2001-12-31 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (EnumToUnderlying): This function is used to get - the underlying type from an enumeration, because it does not - always work. - - * constant.cs: Use the I4_S form for values between -128 and 127. - - * statement.cs (Block.LookupLabel): Looks up a label. - (Block): Drop support for labeled blocks. - - (LabeledStatement): New kind of statement that represents a label - only. - - (Goto): Finally implement this bad boy. - - * cs-parser.jay: Update to reflect new mechanism to implement - labels. - -2001-12-30 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs (EmitContext.This): a codegen property that keeps the - a single instance of this instead of creating many different this - instances. - - * delegate.cs (Delegate.DoResolve): Update to use the property; - - * ecore.cs (SimpleName.SimpleNameResolve): Ditto - - * expression.cs (BaseAccess.DoResolve): Ditto. - -2001-12-29 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (methodimpl_attr_type): Add to hold the type - corresponding to System.Runtime.CompilerServices.MethodImplAttribute. - - (InitCoreTypes): Update accordingly. - - * attribute.cs (Resolve): Remember if the attribute is a MethodImplAttribute - so we can quickly store the state. - - (ApplyAttributes): Set the correct implementation flags - for InternalCall methods. - -2001-12-29 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (EmitCall): if a method is not virtual, then do - not use callvirt on it. - - (ArrayAccess.EmitAssign): storing non-builtin value types (ie, - user defined stuff) requires the use of stobj, which takes an - address on the stack instead of an array and an index. So emit - the Ldelema operation for it. - - (EmitStoreOpcode): Use stobj for valuetypes. - - (UnaryMutator.EmitCode): Use the right 1 value depending on - whether we are dealing with int64/uint64, float or doubles. - - * class.cs (TypeContainer.AddConstructor): Fix the logic to define - constructors that I implemented last night. - - (Constructor.IsDefault): Fix to work properly for static - constructors. - - * cs-parser.jay (CheckDef): report method signature errors. - Update error number 103 to be 132. - - * decl.cs: New AdditionResult enumeration value: MethodExists. - Although we do this check for methods later on in the semantic - analysis, catching repeated default constructors is so easy that - we catch these here. - - * expression.cs (Binary.DoNumericPromotions): Fix the uint64 type - promotions code. - - (ParameterReference.EmitAssign, Emit): handle - bools as bytes. - - (ArrayAccess.EmitLoadOpcode): Handle bool type here. - (ArrayAccess.EmitStoreOpcode): ditto. - - * cs-tokenizer.cs (is_punct): Eliminated empty computation. - - * expression.cs (MakeByteBlob): Complete all the missing types - (uint, short, ushort, byte, sbyte) - - * class.cs: Only init instance field initializers on instance - constructors. - - Rename `constructors' to instance_constructors. - - (TypeContainer.AddConstructor): Only add constructors to the list - if it is not static. - - Make sure that we handle default_static_constructor independently - everywhere where we handle instance_constructors - -2001-12-28 Miguel de Icaza <miguel@ximian.com> - - * class.cs: Do not lookup or create a base initializer for a - static constructor. - - (ConstructorInitializer.Resolve): use the proper type to lookup - for constructors. - - * cs-parser.jay: Report error 1585 (modifiers between type and name). - - * enum.cs, interface.cs: Remove CloseType, this is taken care by - in DeclSpace. - - * decl.cs: CloseType is now an virtual method, the default - implementation just closes this type. - -2001-12-28 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (DefinePInvokeMethod): Set the implementation flags - to PreserveSig by default. Also emit HideBySig on such methods. - - Basically, set the defaults to standard values. - - * expression.cs (Invocation.BetterFunction): We need to make sure that for each - argument, if candidate is better, it can't be worse than the best ! - - (Invocation): Re-write bits to differentiate between methods being - applicable in their expanded form and their normal form - for params - methods of course. - - Get rid of use_standard everywhere as only standard conversions are allowed - in overload resolution. - - More spec conformance. - -2001-12-27 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Add --timestamp, to see where the compiler spends - most of its time. - - * ecore.cs (SimpleName.DoResolve): Do not create an implicit - `this' in static code. - - (SimpleName.DoResolve): Implement in terms of a helper function - that allows static-references to be passed upstream to - MemberAccess. - - (Expression.ResolveWithSimpleName): Resolve specially simple - names when called by MemberAccess to implement the special - semantics. - - (Expression.ImplicitReferenceConversion): Handle conversions from - Null to reference types before others, as Null's type is - System.Object. - - * expression.cs (Invocation.EmitCall): Handle the special case of - calling methods declared on a reference type from a ValueType - (Base classes System.Object and System.Enum) - - (MemberAccess.Resolve): Only perform lookups on Enumerations if - the left hand side is a TypeExpr, not on every enumeration. - - (Binary.Resolve): If types are reference types, then do a cast to - object on operators != and == of both arguments. - - * typemanager.cs (FindMembers): Extract instance and static - members if requested. - - * interface.cs (PopulateProperty): Use void_type instead of null - as the return type for the setter method. - - (PopulateIndexer): ditto. - -2001-12-27 Ravi Pratap <ravi@ximian.com> - - * support.cs (ReflectionParameters): Fix minor bug where we - were examining the wrong parameter for the ParamArray attribute. - - Cope with requests for the type of the parameter at position - greater than the params parameter's. We now return the element - type of the params array as that makes more sense. - - * expression.cs (Invocation.IsParamsMethodApplicable): Update - accordingly as we no longer have to extract the element type - ourselves. - - (Invocation.OverloadResolve): Update. - -2001-12-27 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Foreach.GetEnumeratorFilter): Do not compare - against IEnumerator, test whether the return value is a descendant - of the IEnumerator interface. - - * class.cs (Indexer.Define): Use an auxiliary method to implement - the other bits of the method definition. Begin support for - explicit interface implementation. - - (Property.DefineMethod): Use TypeManager.void_type instead of null - for an empty return value. - -2001-12-26 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (MemberAccess.ResolveMemberAccess): if we are - dealing with a FieldExpr which is composed of a FieldBuilder, in - the code path we did extract the constant, but we should have - obtained the underlying value to be able to cast it (otherwise we - end up in an infinite loop, this is what Ravi was running into). - - (ArrayCreation.UpdateIndices): Arrays might be empty. - - (MemberAccess.ResolveMemberAccess): Add support for section - 14.5.4.1 that deals with the special case of E.I when E is a type - and something else, that I can be a reference to a static member. - - (ArrayCreation.MakeByteBlob): It is not an error to not be able to - handle a particular array type to create byte blobs, it is just - something we dont generate byteblobs for. - - * cs-tokenizer.cs (get_cmd_arg): Ignore \r in commands and - arguments. - - * location.cs (Push): remove the key from the hashtable that we - are about to add. This happens for empty files. - - * driver.cs: Dispose files after we have parsed them. - - (tokenize): new function that only runs the tokenizer on its - input, for speed testing. - -2001-12-26 Ravi Pratap <ravi@ximian.com> - - * class.cs (Event.Define): Define the private field only if there - are no accessors defined. - - * expression.cs (ResolveMemberAccess): If there is no associated - field with the event, that means we have an event defined with its - own accessors and we should flag error cs0070 since transforming - ourselves into a field is not valid in that case. - - * ecore.cs (SimpleName.DoResolve): Same as above. - - * attribute.cs (DefinePInvokeMethod): Set the default calling convention - and charset to sane values. - -2001-12-25 Ravi Pratap <ravi@ximian.com> - - * assign.cs (DoResolve): Perform check on events only if they - are being accessed outside the declaring type. - - * cs-parser.jay (event_declarations): Update rules to correctly - set the type of the implicit parameter etc. - - (add_accessor, remove_accessor): Set current local parameters. - - * expression.cs (Binary): For delegate addition and subtraction, - cast the return value from the method into the appropriate delegate - type. - -2001-12-24 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (RegisterDelegateData, GetDelegateData): Get rid - of these as the workaround is unnecessary. - - * delegate.cs (NewDelegate.DoResolve): Get rid of bits which registered - delegate data - none of that is needed at all. - - Re-write bits to extract the instance expression and the delegate method - correctly. - - * expression.cs (Binary.ResolveOperator): Handle the '-' binary operator - on delegates too. - - * attribute.cs (ApplyAttributes): New method to take care of common tasks - of attaching attributes instead of duplicating code everywhere. - - * everywhere : Update code to do attribute emission using the above method. - -2001-12-23 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (IsParamsMethodApplicable): if there are not - parameters, return immediately. - - * ecore.cs: The 0 literal can be implicity converted to an enum - type. - - (SimpleName.DoResolve): First lookup the type, then lookup the - members. - - (FieldExpr.Emit): If the InstanceExpression is a ValueType, we - want to get its address. If the InstanceExpression is not - addressable, store the result in a temporary variable, then get - the address of it. - - * codegen.cs: Only display 219 errors on warning level or above. - - * expression.cs (ArrayAccess): Make it implement the - IMemoryLocation interface. - - (Binary.DoResolve): handle the operator == (object a, object b) - and operator != (object a, object b) without incurring into a - BoxedCast (because 5 != o should never be performed). - - Handle binary enumerator operators. - - (EmitLoadOpcode): Use Ldelema if the object we are loading is a - value type, otherwise use Ldelem_ref. - - Use precomputed names; - - (AddressOf): Implement address of - - * cs-parser.jay (labeled_statement): Fix recursive block - addition by reworking the production. - - * expression.cs (New.DoEmit): New has a special case: - - If we are dealing with a ValueType, we have a few - situations to deal with: - - * The target of New is a ValueType variable, that is - easy, we just pass this as the variable reference - - * The target of New is being passed as an argument, - to a boxing operation or a function that takes a - ValueType. - - In this case, we need to create a temporary variable - that is the argument of New. - - -2001-12-23 Ravi Pratap <ravi@ximian.com> - - * rootcontext.cs (LookupType): Check that current_type is not null before - going about looking at nested types. - - * ecore.cs (EventExpr.EmitAddOrRemove): Rename from EmitAssign as we do - not implement the IAssignMethod interface any more. - - * expression.cs (MemberAccess.ResolveMemberAccess): Handle EventExprs specially - where we tranform them into FieldExprs if they are being resolved from within - the declaring type. - - * ecore.cs (SimpleName.DoResolve): Do the same here. - - * assign.cs (DoResolve, Emit): Clean up code considerably. - - * ../errors/bug10.cs : Add. - - * ../errors/cs0070.cs : Add. - - * typemanager.cs : Use PtrHashtable for Delegate data hashtable etc. - - * assign.cs : Get rid of EventIsLocal everywhere. - -2001-12-23 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (ConvertIntLiteral): finished the implementation. - - * statement.cs (SwitchLabel): Convert the value we are using as a - key before looking up the table. - -2001-12-22 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs (EmitTopBlock): Require a Location argument now. - - * cs-parser.jay (constructor_declarator): We need to setup - current_local_parameters before we parse the - opt_constructor_initializer, to allow the variables to be bound - to the constructor arguments. - - * rootcontext.cs (LookupType): First lookup nested classes in our - class and our parents before we go looking outside our class. - - * expression.cs (ConstantFold): Extract/debox the values at the - beginnning. - - * rootcontext.cs (EmitCode): Resolve the constants first before we - resolve the types. This is not really needed, but it helps debugging. - - * statement.cs: report location. - - * cs-parser.jay: pass location to throw statement. - - * driver.cs: Small bug fix. - - * report.cs: Updated format to be 4-zero filled digits. - -2001-12-22 Ravi Pratap <ravi@ximian.com> - - * expression.cs (CheckIndices): Fix minor bug where the wrong - variable was being referred to ;-) - - (DoEmit): Do not call EmitStaticInitializers when the - underlying type is System.Object. - -2001-12-21 Ravi Pratap <ravi@ximian.com> - - * ecore.cs (EventExpr.Resolve): Implement to correctly set the type - and do the usual workaround for SRE. - - * class.cs (MyEventBuilder.EventType): New member to get at the type - of the event, quickly. - - * expression.cs (Binary.ResolveOperator): Handle delegate addition. - - * assign.cs (Assign.DoResolve): Handle the case when the target - is an EventExpr and perform the necessary checks. - - * ecore.cs (EventExpr.EmitAssign): Implement the IAssignMethod - interface. - - (SimpleName.MemberStaticCheck): Include check for EventExpr. - - (EventExpr): Set the type in the constructor itself since we - are meant to be born fully resolved. - - (EventExpr.Define): Revert code I wrote earlier. - - * delegate.cs (NewDelegate.Resolve): Handle the case when the MethodGroup's - instance expression is null. The instance expression is a This in that case - or a null, depending on whether it is a static method or not. - - Also flag an error if the reference to a method is ambiguous i.e the MethodGroupExpr - refers to more than one method. - - * assign.cs (DoResolve): Check whether the event belongs to the same Type container - and accordingly flag errors. - -2001-12-21 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Throw.Emit): Add support for re-throwing exceptions. - -2001-12-22 Miguel de Icaza <miguel@ximian.com> - - * location.cs (ToString): Provide useful rutine. - -2001-12-21 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (Expression.ConvertIntLiteral): Do not return Constant - objects, return the actual integral boxed. - - * statement.cs (SwitchLabel): define an ILLabel for each - SwitchLabel. - - (Switch.CheckSwitch): If the value is a Literal, extract - the underlying literal. - - Also in the unused hashtable we had, add the SwitchLabel so we can - quickly look this value up. - - * constant.cs: Implement a bunch of new constants. Rewrite - Literal based on this. Made changes everywhere to adapt to this. - - * expression.cs (Expression.MakeByteBlob): Optimize routine by - dereferencing array only once, and also copes with enumrations. - - bytes are two bytes wide, not one. - - (Cast): Perform constant conversions. - - * ecore.cs (TryImplicitIntConversion): Return literals instead of - wrappers to the literals here. - - * expression.cs (DoNumericPromotions): long literals can converted - to ulong implicity (this is taken care of elsewhere, but I was - missing this spot). - - * ecore.cs (Expression.Literalize): Make the return type Literal, - to improve type checking. - - * rootcontext.cs: Lookup for nested classes in our class hierarchy. - -2001-12-20 Miguel de Icaza <miguel@ximian.com> - - * literal.cs: Revert code from ravi that checked the bounds. The - bounds are sane by the definition of the type itself. - - * typemanager.cs: Fix implementation of ImplementsInterface. We - need to actually look up in our parent hierarchy for interfaces - implemented. - - * const.cs: Use the underlying type for enumerations - - * delegate.cs: Compute the basename for the delegate creation, - that should fix the delegate test case, and restore the correct - Type Lookup semantics in rootcontext - - * rootcontext.cs: Revert Ravi's last patch. The correct way of - referencing a nested type with the Reflection API is using the "+" - sign. - - * cs-parser.jay: Do not require EOF token at the end. - -2001-12-20 Ravi Pratap <ravi@ximian.com> - - * rootcontext.cs (LookupType): Concatenate type names with - a '.' instead of a '+' The test suite passes again. - - * enum.cs (Enum.DefineEnum): Set RTSpecialName on the 'value__' - field of the enumeration. - - * expression.cs (MemberAccess.ResolveMemberAccess): Add support for - the case when the member is an EventExpr. - - * ecore.cs (EventExpr.InstanceExpression): Every event which is not - static has an associated instance expression. - - * typemanager.cs (RegisterEvent): The usual workaround, now for events. - - (GetAddMethod, GetRemoveMethod): Workarounds, as usual. - - * class.cs (Event.Define): Register event and perform appropriate checks - for error #111. - - We define the Add and Remove methods even if the use provides none because - in that case, we provide default implementations ourselves. - - Define a private field of the type of the event. This is done by the CSC compiler - and we should be doing it too ;-) - - * typemanager.cs (delegate_combine_delegate_delegate, delegate_remove_delegate_delegate): - More methods we use in code we generate. - - (multicast_delegate_type, delegate_type): Two separate types since the distinction - is important. - - (InitCoreTypes): Update accordingly for the above. - - * class.cs (Event.Emit): Generate code for default accessors that we provide - - (EmitDefaultMethod): Do the job in the above. - - * delegate.cs (DefineDelegate): Use TypeManager.multicast_delegate_type in the - appropriate place. - -2001-12-20 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Indexer.Define): Fix bug, we were setting both Get/Set - builders even if we were missing one. - - * interface.cs, class.cs, enum.cs: When calling DefineNestedType - pass the Basename as our class name instead of the Name. The - basename will be correctly composed for us. - - * parameter.cs (Paramters): Now takes a Location argument. - - * decl.cs (DeclSpace.LookupType): Removed convenience function and - make all the code call directly LookupType in RootContext and take - this chance to pass the Location information everywhere. - - * Everywhere: pass Location information. - -2001-12-19 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Constructor.Define): Updated way of detecting the - length of the parameters. - - (TypeContainer.DefineType): Use basename as the type name for - nested types. - - (TypeContainer.Define): Do not recursively define types here, as - definition is taken care in order by the RootContext. - - * tree.cs: Keep track of namespaces in a per-file basis. - - * parameter.cs (Parameter.ComputeSignature): Update to use - DeclSpace. - - (Parameters.GetSignature): ditto. - - * interface.cs (InterfaceMethod.GetSignature): Take a DeclSpace - instead of a TypeContainer. - - (Interface.SemanticAnalysis): Use `this' instead of our parent to - resolve names. Because we need to be resolve in our context, not - our parents. - - * driver.cs: Implement response files. - - * class.cs (TypeContainer.DefineType): If we are defined, do not - redefine ourselves. - - (Event.Emit): Emit the code for add/remove handlers. - (Event.Define): Save the MethodBuilders for add/remove. - - * typemanager.cs: Use pair here too. - - * cs-parser.jay: Replaced use of DictionaryEntry for Pair because - DictionaryEntry requires the first argument to be non-null. - - (enum_declaration): Compute full name for registering the - enumeration. - - (delegate_declaration): Instead of using - formal_parameter_list, use opt_formal_parameter_list as the list - can be empty. - - * cs-tokenizer.cs (PropertyParsing): renamed from `properties' - (EventParsing): New property that controls whether `add' and - `remove' are returned as tokens or identifiers (for events); - -2001-12-19 Ravi Pratap <ravi@ximian.com> - - * class.cs (Event.Define): Revamp use of EventBuilder completely. We now - use MyEventBuilder only and let it wrap the real builder for us. - - (MyEventBuilder): Revamp constructor etc. - - Implement all operations that we perform on EventBuilder in precisely the same - way here too. - - (FindMembers): Update to use the EventBuilder member. - - (Event.Emit): Update accordingly. - -2001-12-18 Ravi Pratap <ravi@ximian.com> - - * class.cs (MyEventBuilder.Set*): Chain to the underlying builder - by calling the appropriate methods. - - (GetCustomAttributes): Make stubs as they cannot possibly do anything - useful. - - (Event.Emit): Use MyEventBuilder everywhere - even to set attributes. - -2001-12-17 Ravi Pratap <ravi@ximian.com> - - * delegate.cs (Delegate.Populate): Check that the return type - and various parameters types are indeed accessible. - - * class.cs (Constructor.Define): Same here. - - (Field.Define): Ditto. - - (Event.Define): Ditto. - - (Operator.Define): Check that the underlying Method defined itself - correctly - so it's MethodBuilder should not be null. - - * delegate.cs (DelegateInvocation.DoResolve): Bale out if the type of the Instance - expression happens to be null. - - * class.cs (MyEventBuilder): Workaround for SRE lameness. Implement various abstract - members but as of now we don't seem to be able to do anything really useful with it. - - (FindMembers): Handle events separately by returning the MyEventBuilder of the event, - not the EventBuilder. - -2001-12-18 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Add support for defines. - Add support for #if, #elif, #else, #endif - - (eval_var): evaluates a variable. - (eval): stubbed for evaluating functions. - - * cs-parser.jay: Pass the defines information - - * driver.cs: Add --define command line option. - - * decl.cs: Move MemberCore here. - - Make it the base class for DeclSpace. This allows us to catch and - report 108 and 109 for everything now. - - * class.cs (TypeContainer.Define): Extract all the members - before populating and emit the warning 108 (new keyword required - to override) instead of having each member implement this. - - (MemberCore.Define): New abstract method, we will be using this in - the warning reporting engine in Populate. - - (Operator.Define): Adjust to new MemberCore protocol. - - * const.cs (Const): This does not derive from Expression, it is a - temporary object we use to create fields, it is a MemberCore. - - * class.cs (Method.Define): Allow the entry point to be in a - specific class. - - * driver.cs: Rewrite the argument handler to clean it up a bit. - - * rootcontext.cs: Made it just an auxiliary namespace feature by - making everything static. - - * driver.cs: Adapt code to use RootContext type name instead of - instance variable. - - * delegate.cs: Remove RootContext argument. - - * class.cs: (Struct, TypeContainer, Class): Remove RootContext - argument. - - * class.cs (Event.Define): The lookup can fail. - - * cs-tokenizer.cs: Begin implementation of pre-procesor. - - * expression.cs: Resolve the this instance before invoking the code. - -2001-12-17 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Add a production in element_access that allows - the thing to become a "type" reference. This way we can parse - things like "(string [])" as a type. - - Note that this still does not handle the more complex rules of - casts. - - - * delegate.cs (Delegate.Populate): Register the delegage constructor builder here. - - * ecore.cs: (CopyNewMethods): new utility function used to - assemble the list of methods from running FindMembers. - - (MemberLookup): Rework FindMembers so that - -2001-12-16 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer): Remove Delegates who fail to be - defined. - - * delegate.cs (Populate): Verify that we dont get null return - values. TODO: Check for AsAccessible. - - * cs-parser.jay: Use basename to emit error 574 (destructor should - have the same name as container class), not the full name. - - * cs-tokenizer.cs (adjust_int): Fit the integer in the best - possible representation. - - Also implements integer type suffixes U and L. - -2001-12-15 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ArrayCreation.DoResolve): We need to do the - argument resolution *always*. - - * decl.cs: Make this hold the namespace. Hold the root context as - well. - (LookupType): Move here. - - * enum.cs, class.cs, interface.cs: Adapt to new hierarchy. - - * location.cs (Row, Name): Fixed the code, it was always returning - references to the first file. - - * interface.cs: Register properties defined through interfaces. - - * driver.cs: Add support for globbing on the command line - - * class.cs (Field): Make it derive from MemberCore as well. - (Event): ditto. - -2001-12-15 Ravi Pratap <ravi@ximian.com> - - * class.cs (Event::Define): Check that the type of the event is a delegate - type else flag error #66. - - Also, re-use TypeContainer.MethodModifiersValid here too as the rules are the - same. - - * attribute.cs (DefinePInvokeMethod): Handle named arguments and process - values of EntryPoint, CharSet etc etc. - - Pass in the values to TypeBuilder.DefinePInvokeMethod; determine Type etc neatly. - - * class.cs (FindMembers): If a method is in transit, its MethodBuilder will - be null and we should ignore this. I am not sure if this is really clean. Apparently, - there's no way of avoiding hitting this because the call is coming from SimpleName.DoResolve, - which needs this to do its work. - - * ../errors/cs0066.cs : Add. - -2001-12-14 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs: (GetPropertyGetter, GetPropertyGetter): New - helper functions. - - * class.cs: (MethodSignature.MethodSignature): Removed hack that - clears out the parameters field. - (MemberSignatureCompare): Cleanup - - (MemberCore): New base class used to share code between MethodCore - and Property. - - (RegisterRequiredImplementations) BindingFlags.Public requires - either BindingFlags.Instace or Static. Use instance here. - - (Property): Refactored code to cope better with the full spec. - - * parameter.cs (GetParameterInfo): Return an empty array instead - of null on error. - - * class.cs (Property): Abstract or extern properties have no bodies. - - * parameter.cs (GetParameterInfo): return a zero-sized array. - - * class.cs (TypeContainer.MethodModifiersValid): Move all the - method modifier validation to the typecontainer so we can reuse - this on properties. - - (MethodCore.ParameterTypes): return an empty sized array of types. - - (Property.Define): Test property modifier validity. - - Add tests for sealed/override too. - - (Method.Emit): abstract or extern methods have no bodies. - -2001-12-14 Ravi Pratap <ravi@ximian.com> - - * class.cs (Method.IsPInvoke): Get rid of it as it is an expensive - thing. - - (Method::Define, ::Emit): Modify accordingly. - - * expression.cs (Invocation::OverloadResolve): Handle error # 121. - - (ArrayCreation::MakeByteBlob): Handle floats and doubles. - - * makefile: Pass in /unsafe. - -2001-12-13 Miguel de Icaza <miguel@ximian.com> - - * class.cs (MakeKey): Kill routine. - - * class.cs (TypeContainer.Define): Correctly define explicit - method implementations (they require the full interface name plus - the method name). - - * typemanager.cs: Deply the PtrHashtable here and stop using the - lame keys. Things work so much better. - - This of course broke everyone who depended on `RegisterMethod' to - do the `test for existance' test. This has to be done elsewhere. - - * support.cs (PtrHashtable): A hashtable that avoid comparing with - the object stupid Equals method (because, that like fails all over - the place). We still do not use it. - - * class.cs (TypeContainer.SetRequiredInterface, - TypeContainer.RequireMethods): Killed these two routines and moved - all the functionality to RegisterRequiredImplementations. - - (TypeContainer.RegisterRequiredImplementations): This routine now - registers all the implementations required in an array for the - interfaces and abstract methods. We use an array of structures - which can be computed ahead of time to reduce memory usage and we - also assume that lookups are cheap as most classes will not - implement too many interfaces. - - We also avoid creating too many MethodSignatures. - - (TypeContainer.IsInterfaceMethod): Update and optionally does not - clear the "pending" bit if we find that there are problems with - the declaration. - - (TypeContainer.VerifyPendingMethods): Update to report errors of - methods that look like implementations but are not. - - (TypeContainer.Define): Add support for explicit interface method - implementation. - -2001-12-12 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs: Keep track of the parameters here instead of - being a feature of the TypeContainer. - - * class.cs: Drop the registration of parameters here, as - InterfaceMethods are also interface declarations. - - * delegate.cs: Register methods with the TypeManager not only with - the TypeContainer. This code was buggy. - - * interface.cs: Full registation here. - -2001-12-11 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Remove reducer for binary expressions, it can not - be done this way. - - * const.cs: Put here the code that used to go into constant.cs - - * constant.cs: Put here the code for constants, this is a new base - class for Literals. - - * literal.cs: Make Literal derive from Constant. - -2001-12-09 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Return.Emit): Report error 157 if the user - attempts to return from a finally block. - - (Return.Emit): Instead of emitting a return, jump to the end of - the function. - - * codegen.cs (EmitContext): ReturnValue, ReturnLabel: new - LocalBuilder to store the result of the function. ReturnLabel is - the target where we jump. - - -2001-12-09 Radek Doulik <rodo@ximian.com> - - * cs-parser.jay: remember alias in current namespace - - * ecore.cs (SimpleName::DoResolve): use aliases for types or - namespaces - - * class.cs (LookupAlias): lookup alias in my_namespace - - * namespace.cs (UsingAlias): add alias, namespace_or_type pair to - aliases hashtable - (LookupAlias): lookup alias in this and if needed in parent - namespaces - -2001-12-08 Miguel de Icaza <miguel@ximian.com> - - * support.cs: - - * rootcontext.cs: (ModuleBuilder) Made static, first step into - making things static. I need this to avoid passing the - TypeContainer when calling ParameterType. - - * support.cs (InternalParameters.ParameterType): Remove ugly hack - that did string manipulation to compute the type and then call - GetType. Use Parameter.ParameterType instead. - - * cs-tokenizer.cs: Consume the suffix for floating values. - - * expression.cs (ParameterReference): figure out whether this is a - reference parameter or not. Kill an extra variable by computing - the arg_idx during emission. - - * parameter.cs (Parameters.GetParameterInfo): New overloaded - function that returns whether a parameter is an out/ref value or not. - - (Parameter.ParameterType): The type of the parameter (base, - without ref/out applied). - - (Parameter.Resolve): Perform resolution here. - (Parameter.ExternalType): The full type (with ref/out applied). - - * statement.cs (Using.Emit, Using.EmitExpression): Implement - support for expressions on the using statement. - -2001-12-07 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Using.EmitLocalVariableDecls): Split the - localvariable handling of the using statement. - - (Block.EmitMeta): Keep track of variable count across blocks. We - were reusing slots on separate branches of blocks. - - (Try.Emit): Emit the general code block, we were not emitting it. - - Check the type of the declaration to be an IDisposable or - something that can be implicity converted to it. - - Emit conversions if required. - - * ecore.cs (EmptyExpression): New utility class. - (Expression.ImplicitConversionExists): New utility function. - -2001-12-06 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Using): Implement. - - * expression.cs (LocalVariableReference): Support read only variables. - - * statement.cs: Remove the explicit emit for the Leave opcode. - (VariableInfo): Add a readonly field. - -2001-12-05 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (ConvCast): new class used to encapsulate the various - explicit integer conversions that works in both checked and - unchecked contexts. - - (Expression.ConvertNumericExplicit): Use new ConvCast class to - properly generate the overflow opcodes. - -2001-12-04 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: The correct type for the EmptyExpression is the - element_type, not the variable type. Ravi pointed this out. - -2001-12-04 Ravi Pratap <ravi@ximian.com> - - * class.cs (Method::Define): Handle PInvoke methods specially - by using DefinePInvokeMethod instead of the usual one. - - * attribute.cs (DefinePInvokeMethod): Implement as this is what is called - above to do the task of extracting information and defining the method. - -2001-12-04 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation::EmitStaticInitializers): Get rid - of the condition for string type. - - (Emit): Move that here. - - (ArrayCreation::CheckIndices): Keep string literals in their expression - form. - - (EmitDynamicInitializers): Handle strings appropriately. - -2001-12-04 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs (EmitContext): Replace multiple variables with a - single pointer to the current Switch statement. - - * statement.cs (GotoDefault, Switch): Adjust to cleaned up - EmitContext. - -2001-12-03 Miguel de Icaza <miguel@ximian.com> - - * statement.cs - - * statement.cs (GotoDefault), cs-parser.jay: Implement `goto - default'. - - (Foreach.Emit): Foreach on arrays was not setting - up the loop variables (for break/continue). - - (GotoCase): Semi-implented. - -2001-12-03 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (CheckAttribute): Handle system attributes by using - Attribute.GetAttributes to examine information we need. - - (GetValidPlaces): Same here. - - * class.cs (Method::Define): Catch invalid use of extern and abstract together. - - * typemanager.cs (dllimport_type): Core type for System.DllImportAttribute. - - * class.cs (Method.IsPinvoke): Used to determine if we are a PInvoke method. - - (Method::Define): Set appropriate flags if we have a DllImport attribute. - - (Method::Emit): Handle the case when we are a PInvoke method. - -2001-12-03 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Use ResolveWithSimpleName on compound names. - -2001-12-02 Ravi Pratap <ravi@ximian.com> - - * constant.cs (EmitConstant): Make sure we resolve the associated expression - before trying to reduce it. - - * typemanager.cs (RegisterConstant, LookupConstant): Implement. - - * constant.cs (LookupConstantValue): Implement. - - (EmitConstant): Use the above in emitting the constant. - - * expression.cs (MemberAccess::ResolveMemberAccess): Handle constants - that are user-defined by doing a LookupConstantValue on them. - - (SimpleName::DoResolve): When we have a FieldExpr, cope with constants - too, like above. - -2001-11-29 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (BaseAccess, BaseIndexer): Also split this out. - - (BaseAccess.DoResolve): Implement. - - (MemberAccess.DoResolve): Split this routine into a - ResolveMemberAccess routine that can be used independently - -2001-11-28 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Probe, Is, As): Split Probe in two classes Is and - As that share bits of the implementation. Is returns a boolean, - while As returns the Type that is being probed. - -2001-12-01 Ravi Pratap <ravi@ximian.com> - - * enum.cs (LookupEnumValue): Re-write various bits, return an object value - instead of a Literal - much easier. - - (EnumInTransit): Remove - utterly useless :-) - - (Populate): Re-write bits - remove duplicate code etc. The code is much neater now. - - * expression.cs (MemberLookup): Cope with user-defined enums when they are in transit. - - * enum.cs (LookupEnumValue): Auto-compute next values by going down the dependency - chain when we have no associated expression. - -2001-11-30 Ravi Pratap <ravi@ximian.com> - - * constant.cs (Define): Use Location while reporting the errror. - - Also emit a warning when 'new' is used and there is no inherited - member to hide. - - * enum.cs (EnumInTransit): Used to tell if an enum type is in the process of being - populated. - - (LookupEnumValue): Implement to lookup an enum member's value and define it - if necessary. - - (Populate): Re-write accordingly to use the above routine. - -2001-11-27 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (This): Fix prototype for DoResolveLValue to - override the base class DoResolveLValue. - - * cs-parser.cs: Report errors cs574 and cs575 (destructor - declarations) - - * ecore.cs (FieldExpr.EmitAssign): Handle value types specially - (we need to load the address of the field here). This fixes - test-22. - - (FieldExpr.DoResolveLValue): Call the DoResolve - function to initialize the Instance expression. - - * statement.cs (Foreach.Emit): Fix the bug where we did not invoke - correctly the GetEnumerator operation on a value type. - - * cs-parser.jay: Add more simple parsing error catches. - - * statement.cs (Switch): Add support for string switches. - Handle null specially. - - * literal.cs (NullLiteral): Make NullLiteral objects singletons. - -2001-11-28 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (local_constant_declaration): Use declare_local_constant. - - (declare_local_constant): New helper function. - - * statement.cs (AddConstant): Keep a separate record of constants - - (IsConstant): Implement to determine if a variable is a constant. - - (GetConstantExpression): Implement. - - * expression.cs (LocalVariableReference): Handle the case when it is a constant. - - * statement.cs (IsVariableDefined): Re-write. - -2001-11-27 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::FindMembers): Look for constants - in the case when we are looking for MemberTypes.Field - - * expression.cs (MemberAccess::DoResolve): Check that in the - case we are a FieldExpr and a Literal, we are not being accessed - by an instance reference. - - * cs-parser.jay (local_constant_declaration): Implement. - - (declaration_statement): Implement for constant declarations. - -2001-11-26 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Switch): Catch double defaults. - - (Switch): More work on the switch() statement - implementation. It works for integral values now, need to finish - string support. - - -2001-11-24 Miguel de Icaza <miguel@ximian.com> - - * ecore.cs (Expression.ConvertIntLiteral): New function to convert - integer literals into other integer literals. To be used by - switch. - -2001-11-24 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation): Get rid of ArrayExprs : we save - some memory. - - (EmitDynamicInitializers): Cope with the above since we extract data - directly from ArrayData now. - - (ExpectInitializers): Keep track of whether initializers are mandatory - or not. - - (Bounds): Make it a hashtable to prevent the same dimension being - recorded for every element in that dimension. - - (EmitDynamicInitializers): Fix bug which prevented the Set array method - from being found. - - Also fix bug which was causing the indices to be emitted in the reverse - order. - -2001-11-24 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ArrayCreation): Implement the bits that Ravi left - unfinished. They do not work, because the underlying code is - sloppy. - -2001-11-22 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Remove bogus fixme. - - * statement.cs (Switch, SwitchSection, SwithLabel): Started work - on Switch statement. - -2001-11-23 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (IsDelegateType, IsEnumType): Fix logic to determine - the same. - - * expression.cs (ArrayCreation::CheckIndices): Get rid of the require_constant - parameter. Apparently, any expression is allowed. - - (ValidateInitializers): Update accordingly. - - (CheckIndices): Fix some tricky bugs thanks to recursion. - - * delegate.cs (NewDelegate::DoResolve): Re-write large portions as - I was being completely brain-dead. - - (VerifyMethod, VerifyApplicability, VerifyDelegate): Make static - and re-write acordingly. - - (DelegateInvocation): Re-write accordingly. - - * expression.cs (ArrayCreation::Emit): Handle string initialization separately. - - (MakeByteBlob): Handle types more correctly. - - * expression.cs (ArrayCreation:Emit): Write preliminary code to do - initialization from expressions but it is incomplete because I am a complete - Dodo :-| - -2001-11-22 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (If.Emit): Fix a bug that generated incorrect code - on If. Basically, we have to return `true' (ie, we do return to - our caller) only if both branches of the if return. - - * expression.cs (Binary.Emit): LogicalOr and LogicalAnd are - short-circuit operators, handle them as short circuit operators. - - (Cast.DoResolve): Resolve type. - (Cast.Cast): Take an expression as the target type. - - * cs-parser.jay (cast_expression): Remove old hack that only - allowed a limited set of types to be handled. Now we take a - unary_expression and we resolve to a type during semantic - analysis. - - Use the grammar productions from Rhys to handle casts (this is - not complete like Rhys syntax yet, we fail to handle that corner - case that C# has regarding (-x), but we will get there. - -2001-11-22 Ravi Pratap <ravi@ximian.com> - - * class.cs (EmitFieldInitializer): Take care of the case when we have a - field which is an array type. - - * cs-parser.jay (declare_local_variables): Support array initialization too. - - * typemanager.cs (MakeKey): Implement. - - (everywhere): Use the above appropriately. - - * cs-parser.jay (for_statement): Update for array initialization while - declaring variables. - - * ecore.cs : The error message was correct, it's the variable's names that - were misleading ;-) Make the code more readable. - - (MemberAccess::DoResolve): Fix the code which handles Enum literals to set - the correct type etc. - - (ConvertExplicit): Handle Enum types by examining the underlying type. - -2001-11-21 Ravi Pratap <ravi@ximian.com> - - * parameter.cs (GetCallingConvention): Always return - CallingConventions.Standard for now. - -2001-11-22 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Binary.ResolveOperator): Update the values of `l' - and `r' after calling DoNumericPromotions. - - * ecore.cs: Fix error message (the types were in the wrong order). - - * statement.cs (Foreach.ProbeCollectionType): Need to pass - BindingFlags.Instance as well - - * ecore.cs (Expression.TryImplicitIntConversion): Wrap the result - implicit int literal conversion in an empty cast so that we - propagate the right type upstream. - - (UnboxCast): new class used to unbox value types. - (Expression.ConvertExplicit): Add explicit type conversions done - by unboxing. - - (Expression.ImplicitNumericConversion): Oops, forgot to test for - the target type before applying the implicit LongLiterals to ULong - literal cast. - -2001-11-21 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay (for_statement): Reworked the way For works: now - we declare manually any variables that are introduced in - for_initializer to solve the problem of having out-of-band code - emition (that is what got for broken). - - (declaration_statement): Perform the actual variable declaration - that used to be done in local_variable_declaration here. - - (local_variable_declaration): Do not declare anything, just pass - the information on a DictionaryEntry - -2001-11-20 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation::CheckIndices): The story continues :-) Complete - re-write of the logic to now make it recursive. - - (UpdateIndices): Re-write accordingly. - - Store element data in a separate ArrayData list in the above methods. - - (MakeByteBlob): Implement to dump the array data into a byte array. - -2001-11-19 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation): Factor out some code from ValidateInitializers - into CheckIndices. - - * constant.cs (Define): Implement. - - (EmitConstant): Re-write fully. - - Pass in location info. - - * class.cs (Populate, Emit): Call Constant::Define and Constant::EmitConstant - respectively. - - * cs-parser.jay (constant_declarator): Use VariableDeclaration instead of - DictionaryEntry since we need location info too. - - (constant_declaration): Update accordingly. - - * expression.cs (ArrayCreation): Make ValidateInitializers simpler by factoring - code into another method : UpdateIndices. - -2001-11-18 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation::ValidateInitializers): Update to perform - some type checking etc. - -2001-11-17 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation::ValidateInitializers): Implement - bits to provide dimension info if the user skips doing that. - - Update second constructor to store the rank correctly. - -2001-11-16 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ArrayCreation::ValidateInitializers): Poke around - and try to implement. - - * ../errors/cs0150.cs : Add. - - * ../errors/cs0178.cs : Add. - -2001-11-16 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: Implement foreach on multi-dimensional arrays. - - * parameter.cs (Parameters.GetParameterByName): Also lookup the - name of the params argument. - - * expression.cs: Use EmitStoreOpcode to get the right opcode while - initializing the array. - - (ArrayAccess.EmitStoreOpcode): move the opcode generation here, so - we can use this elsewhere. - - * statement.cs: Finish implementation of foreach for single - dimension arrays. - - * cs-parser.jay: Use an out-of-band stack to pass information - around, I wonder why I need this. - - foreach_block: Make the new foreach_block the current_block. - - * parameter.cs (Parameters.GetEmptyReadOnlyParameters): New - function used to return a static Parameters structure. Used for - empty parameters, as those are created very frequently. - - * cs-parser.jay, class.cs: Use GetEmptyReadOnlyParameters - -2001-11-15 Ravi Pratap <ravi@ximian.com> - - * interface.cs : Default modifier is private, not public. The - make verify test passes again. - -2001-11-15 Ravi Pratap <ravi@ximian.com> - - * support.cs (ReflectionParameters): Fix logic to determine - whether the last parameter is a params one. Test 9 passes again. - - * delegate.cs (Populate): Register the builders we define with - RegisterParameterForBuilder. Test 19 passes again. - - * cs-parser.jay (property_declaration): Reference $6 instead - of $$ to get at the location. - - (indexer_declaration): Similar stuff. - - (attribute): Ditto. - - * class.cs (Property): Register parameters for the Get and Set methods - if they exist. Test 23 passes again. - - * expression.cs (ArrayCreation::Emit): Pass null for the method in the - call to EmitArguments as we are sure there aren't any params arguments. - Test 32 passes again. - - * suppor.cs (ParameterDesc, ParameterModifier): Fix trivial bug causing - IndexOutOfRangeException. - - * class.cs (Property::Define): Register property using TypeManager.RegisterProperty - Test 33 now passes again. - -2001-11-15 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Kill horrendous hack ($??? = lexer.Location) that - broke a bunch of things. Will have to come up with a better way - of tracking locations. - - * statement.cs: Implemented foreach for single dimension arrays. - -2001-11-09 Miguel de Icaza <miguel@ximian.com> - - * enum.cs (Enum.Emit): Delay the lookup of loc until we run into - an error. This removes the lookup from the critical path. - - * cs-parser.jay: Removed use of temporary_loc, which is completely - broken. - -2001-11-14 Miguel de Icaza <miguel@ximian.com> - - * support.cs (ReflectionParameters.ParameterModifier): Report - whether the argument is a PARAMS argument or not. - - * class.cs: Set the attribute `ParamArrayAttribute' on the - parameter argument. - - * typemanager.cs: Define param_array_type (ParamArrayAttribute) - and cons_param_array_attribute (ConstructorInfo for - ParamArrayAttribute)., - - * codegen.cs: Emit the return using the `Return' statement, that - way we can report the error correctly for missing return values. - - * class.cs (Method.Emit): Clean up. - - * expression.cs (Argument.Resolve): Take another argument: the - location where this argument is used. Notice that this is not - part of the "Argument" class as to reduce the size of the - structure (we know the approximate location anyways). - - Test if the argument is a variable-reference, if not, then - complain with a 206. - - (Argument.Emit): Emit addresses of variables. - - (Argument.FullDesc): Simplify. - - (Invocation.DoResolve): Update for Argument.Resolve. - - (ElementAccess.DoResolve): ditto. - - * delegate.cs (DelegateInvocation.Emit): Invocation of Invoke - method should be virtual, as this method is always virtual. - - (NewDelegate.DoResolve): Update for Argument.Resolve. - - * class.cs (ConstructorInitializer.DoResolve): ditto. - - * attribute.cs (Attribute.Resolve): ditto. - -2001-11-13 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Foreach.Emit): Use EmitAssign instead of Store. - - * expression.cs (ParameterReference): Drop IStackStorage and implement - IAssignMethod instead. - - (LocalVariableReference): ditto. - - * ecore.cs (FieldExpr): Drop IStackStorage and implement - IAssignMethod instead. - -2001-11-13 Miguel de Icaza <miguel@ximian.com> - - * parameter.cs, expression.cs, class.cs, ecore.cs: Made all - enumerations that are used in heavily used structures derive from - byte in a laughable and pathetic attempt to reduce memory usage. - This is the kind of pre-optimzations that you should not do at - home without adult supervision. - - * expression.cs (UnaryMutator): New class, used to handle ++ and - -- separatedly from the other unary operators. Cleans up the - code, and kills the ExpressionStatement dependency in Unary. - - (Unary): Removed `method' and `Arguments' from this class, making - it smaller, and moving it all to SimpleCall, so I can reuse this - code in other locations and avoid creating a lot of transient data - strucutres when not required. - - * cs-parser.jay: Adjust for new changes. - -2001-11-11 Miguel de Icaza <miguel@ximian.com> - - * enum.cs (Enum.Populate): If there is a failure during - definition, return - - * cs-parser.jay (opt_enum_base): we used to catch type errors - here, but this is really incorrect. The type error should be - catched during semantic analysis. - -2001-12-11 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (operator_declarator, conversion_operator_declarator): Set - current_local_parameters as expected since I, in my stupidity, had forgotten - to do this :-) - - * attribute.cs (GetValidPlaces): Fix stupid bug. - - * class.cs (Method::Emit): Perform check on applicability of attributes. - - (Constructor::Emit): Ditto. - - (Field::Emit): Ditto. - - (Field.Location): Store location information. - - (Property, Event, Indexer, Operator): Ditto. - - * cs-parser.jay (field_declaration): Pass in location for each field. - - * ../errors/cs0592.cs : Add. - -2001-11-12 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (attribute_usage_type): New static member for System.AttributeUsage. - - (InitCoreTypes): Update accordingly. - - (RegisterAttrType, LookupAttr): Implement. - - * attribute.cs (Attribute.Targets, AllowMultiple, Inherited): New fields to hold - info about the same. - - (Resolve): Update to populate the above as necessary. - - (Error592): Helper. - - (GetValidPlaces): Helper to the above. - - (CheckAttribute): Implement to perform validity of attributes on declarative elements. - - * class.cs (TypeContainer::Emit): Update attribute emission code to perform checking etc. - -2001-11-12 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (Attribute::Resolve): Expand to handle named arguments too. - - * ../errors/cs0617.cs : Add. - -2001-11-11 Ravi Pratap <ravi@ximian.com> - - * enum.cs (Emit): Rename to Populate to be more consistent with what - we expect it to do and when exactly it is called. - - * class.cs, rootcontext.cs : Update accordingly. - - * typemanager.cs (RegisterField, GetValue): Workarounds for the fact that - FieldInfo.GetValue does not work on dynamic types ! S.R.E lameness strikes again ! - - * enum.cs (Populate): Register fields with TypeManager.RegisterField. - - * expression.cs (MemberAccess.DoResolve): Adjust code to obtain the value - of a fieldinfo using the above, when dealing with a FieldBuilder. - -2001-11-10 Ravi Pratap <ravi@ximian.com> - - * ../errors/cs0031.cs : Add. - - * ../errors/cs1008.cs : Add. - - * ../errrors/cs0543.cs : Add. - - * enum.cs (DefineEnum): Check the underlying type and report an error if not a valid - enum type. - - (FindMembers): Implement. - - * typemanager.cs (FindMembers): Re-write to call the appropriate methods for - enums and delegates too. - - (enum_types): Rename to builder_to_enum. - - (delegate_types): Rename to builder_to_delegate. - - * delegate.cs (FindMembers): Implement. - -2001-11-09 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (IsEnumType): Implement. - - * enum.cs (Emit): Re-write parts to account for the underlying type - better and perform checking etc. - - (GetNextDefaultValue): Helper to ensure we don't overshoot max value - of the underlying type. - - * literal.cs (GetValue methods everywhere): Perform bounds checking and return - value - - * enum.cs (error31): Helper to report error #31. - - * cs-parser.jay (enum_declaration): Store location of each member too. - - * enum.cs (member_to_location): New hashtable. - - (AddEnumMember): Update location hashtable. - - (Emit): Use the location of each member while reporting errors. - -2001-11-09 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: A for_initializer if is a - local_variable_declaration really ammount to have an implicit - block with the variable declaration and no initializer for for. - - * statement.cs (For.Emit): Cope with null initializers. - - This fixes the infinite loop on for initializers. - -2001-11-08 Miguel de Icaza <miguel@ximian.com> - - * enum.cs: More cleanup. - - * ecore.cs: Remove dead code. - - * class.cs (Property.Emit): More simplification. - (Event.Emit): ditto. - - Reworked to have less levels of indentation. - -2001-11-08 Ravi Pratap <ravi@ximian.com> - - * class.cs (Property): Emit attributes. - - (Field): Ditto. - - (Event): Ditto. - - (Indexer): Ditto. - - (Operator): Ditto. - - * enum.cs (Emit): Ditto. - - * rootcontext.cs (ResolveTree, EmitCode, CloseTypes): Do the same for - Enums too. - - * class.cs (Field, Event, etc.): Move attribute generation into the - Emit method everywhere. - - * enum.cs (Enum): Revamp to use the same definition semantics as delegates so - we have a DefineEnum, CloseEnum etc. The previous way of doing things was not right - as we had no way of defining nested enums ! - - * rootcontext.cs : Adjust code accordingly. - - * typemanager.cs (AddEnumType): To keep track of enum types separately. - -2001-11-07 Ravi Pratap <ravi@ximian.com> - - * expression.cs (EvalConstantExpression): Move into ecore.cs - - * enum.cs (Enum): Rename some members and make them public and readonly - according to our convention. - - * modifiers.cs (EnumAttr): Implement as we need to set only visibility flags, - nothing else. - - * enum.cs (Enum::Define): Use the above instead of TypeAttr. - - (Enum::Emit): Write a simple version for now which doesn't try to compute - expressions. I shall modify this to be more robust in just a while. - - * class.cs (TypeContainer::Emit): Make sure we include Enums too. - - (TypeContainer::CloseType): Create the Enum types too. - - * attribute.cs (Resolve): Use the new Reduce method instead of EvalConstantExpression. - - * expression.cs (EvalConstantExpression): Get rid of completely. - - * enum.cs (Enum::Emit): Use the new expression reducer. Implement assigning - user-defined values and other cases. - - (IsValidEnumLiteral): Helper function. - - * expression.cs (ExprClassfromMemberInfo): Modify to not do any literalizing - out there in the case we had a literal FieldExpr. - - (MemberAccess:DoResolve): Do the literalizing of the FieldExpr here. - - (Literalize): Revamp a bit to take two arguments. - - (EnumLiteral): New class which derives from Literal to wrap enum literals. - -2001-11-06 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (compilation_unit): Remove extra opt_attributes for now. - - * expression.cs (ArrayCreation::ValidateInitializers): Implement. - - (Resolve): Use the above to ensure we have proper initializers. - -2001-11-05 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Expression::EvalConstantExpression): New method to - evaluate constant expressions. - - * attribute.cs (Attribute::Resolve): Modify bits to use the above function. - -2001-11-07 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ArrayCreation.Emit): Some bits to initialize data - in an array. - - (Binary.ResolveOperator): Handle operator != (object a, object b) - and operator == (object a, object b); - - (Binary.DoNumericPromotions): Indicate whether the numeric - promotion was possible. - - (ArrayAccess.DoResolve, ArrayAccess.Emit, ArrayAccess.EmitAssign): - Implement. - - Made the ArrayAccess implement interface IAssignMethod instead of - IStackStore as the order in which arguments are passed reflects - this. - - * assign.cs: Instead of using expr.ExprClass to select the way of - assinging, probe for the IStackStore/IAssignMethod interfaces. - - * typemanager.cs: Load InitializeArray definition. - - * rootcontext.cs (RootContext.MakeStaticData): Used to define - static data that can be used to initialize arrays. - -2001-11-05 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Handle operator== and operator!= for booleans. - - (Conditioal.Reduce): Implement reducer for the ?: operator. - - (Conditional.Resolve): Implement dead code elimination. - - (Binary.Resolve): Catch string literals and return a new - concatenated string. - - (Unary.Reduce): Implement reduction of unary expressions. - - * ecore.cs: Split out the expression core handling here. - - (Expression.Reduce): New method used to perform constant folding - and CSE. This is needed to support constant-expressions. - - * statement.cs (Statement.EmitBoolExpression): Pass true and false - targets, and optimize for !x. - -2001-11-04 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (Attribute::Resolve): Implement guts. Note that resolution - of an attribute gives us a CustomAttributeBuilder which we use accordingly to - set custom atttributes. - - * literal.cs (Literal::GetValue): New abstract method to return the actual - value of the literal, cast as an object. - - (*Literal): Implement GetValue method. - - * cs-parser.jay (positional_argument_list, named_argument_list): Add not just plain - expressions to the arraylist but objects of type Argument. - - * class.cs (TypeContainer::Emit): Emit our attributes too. - - (Method::Emit, Constructor::Emit): Ditto. - - * cs-parser.jay (constructor_declaration): Set attributes too, which we seemed - to be ignoring earlier. - -2001-11-03 Ravi Pratap <ravi@ximian.com> - - * attribute.cs (AttributeSection::Define): Implement to do the business - of constructing a CustomAttributeBuilder. - - (Attribute): New trivial class. Increases readability of code. - - * cs-parser.jay : Update accordingly. - - (positional_argument_list, named_argument_list, named_argument): New rules - - (attribute_arguments): Use the above so that we are more correct. - -2001-11-02 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation::IsParamsMethodApplicable): Implement - to perform all checks for a method with a params parameter. - - (Invocation::OverloadResolve): Update to use the above method and therefore - cope correctly with params method invocations. - - * support.cs (InternalParameters::ParameterDesc): Provide a desc for - params too. - - * class.cs (ConstructorInitializer::Resolve): Make sure we look for Non-public - constructors in our parent too because we can't afford to miss out on - protected ones ;-) - - * attribute.cs (AttributeSection): New name for the class Attribute - - Other trivial changes to improve readability. - - * cs-parser.jay (opt_attributes, attribute_section etc.): Modify to - use the new class names. - -2001-11-01 Ravi Pratap <ravi@ximian.com> - - * class.cs (Method::Define): Complete definition for params types too - - (Indexer::Define): Ditto. - - * support.cs (InternalParameters::ParameterType, ParameterDesc, ParameterModifier): - Cope everywhere with a request for info about the array parameter. - -2001-11-01 Ravi Pratap <ravi@ximian.com> - - * tree.cs (RecordNamespace): Fix up to check for the correct key. - - * cs-parser.jay (GetQualifiedIdentifier): New Helper method used in - local_variable_type to extract the string corresponding to the type. - - (local_variable_type): Fixup the action to use the new helper method. - - * codegen.cs : Get rid of RefOrOutParameter, it's not the right way to - go. - - * expression.cs : Clean out code which uses the above. - -2001-10-31 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (RegisterMethod): Check if we already have an existing key - and bale out if necessary by returning a false. - - (RegisterProperty): Ditto. - - * class.cs (everywhere): Check the return value from TypeManager.RegisterMethod - and print out appropriate error messages. - - * interface.cs (everywhere): Ditto. - - * cs-parser.jay (property_declaration, event_declaration, indexer_declaration): Pass - location to constructor. - - * class.cs (Property, Event, Indexer): Update accordingly. - - * ../errors/cs111.cs : Added. - - * expression.cs (Invocation::IsApplicable): New static method to determine applicability - of a method, as laid down by the spec. - - (Invocation::OverloadResolve): Use the above method. - -2001-10-31 Ravi Pratap <ravi@ximian.com> - - * support.cs (InternalParameters): Get rid of crap taking in duplicate info. We - now take a TypeContainer and a Parameters object. - - (ParameterData): Modify return type of ParameterModifier method to be - Parameter.Modifier and not a string. - - (ReflectionParameters, InternalParameters): Update accordingly. - - * expression.cs (Argument::GetParameterModifier): Same here. - - * support.cs (InternalParameters::ParameterType): Find a better way of determining - if we are a ref/out parameter. Actually, the type shouldn't be holding the '&' - symbol in it at all so maybe this is only for now. - -2001-10-30 Ravi Pratap <ravi@ximian.com> - - * support.cs (InternalParameters): Constructor now takes an extra argument - which is the actual Parameters class. - - (ParameterDesc): Update to provide info on ref/out modifiers. - - * class.cs (everywhere): Update call to InternalParameters to pass in - the second argument too. - - * support.cs (ParameterData): Add ParameterModifier, which is a method - to return the modifier info [ref/out etc] - - (InternalParameters, ReflectionParameters): Implement the above. - - * expression.cs (Argument::ParameterModifier): Similar function to return - info about the argument's modifiers. - - (Invocation::OverloadResolve): Update to take into account matching modifiers - too. - - * class.cs (Indexer::Define): Actually define a Parameter object and put it onto - a new SetFormalParameters object which we pass to InternalParameters. - -2001-10-30 Ravi Pratap <ravi@ximian.com> - - * expression.cs (NewArray): Merge into the ArrayCreation class. - -2001-10-29 Ravi Pratap <ravi@ximian.com> - - * expression.cs (NewArray): Merge classes NewBuiltinArray and - NewUserdefinedArray into one as there wasn't much of a use in having - two separate ones. - - * expression.cs (Argument): Change field's name to ArgType from Type. - - (Type): New readonly property which returns the proper type, taking into - account ref/out modifiers. - - (everywhere): Adjust code accordingly for the above. - - * codegen.cs (EmitContext.RefOrOutParameter): New field to determine - whether we are emitting for a ref or out parameter. - - * expression.cs (Argument::Emit): Use the above field to set the state. - - (LocalVariableReference::Emit): Update to honour the flag and emit the - right stuff. - - * parameter.cs (Attributes): Set the correct flags for ref parameters. - - * expression.cs (Argument::FullDesc): New function to provide a full desc. - - * support.cs (ParameterData): Add method ParameterDesc to the interface. - - (ReflectionParameters, InternalParameters): Implement the above method. - - * expression.cs (Invocation::OverloadResolve): Use the new desc methods in - reporting errors. - - (Invocation::FullMethodDesc): Ditto. - -2001-10-29 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Add extra production for the second form of array - creation. - - * expression.cs (ArrayCreation): Update to reflect the above - change. - - * Small changes to prepare for Array initialization. - -2001-10-28 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (ImplementsInterface): interface might be null; - Deal with this problem; - - Also, we do store negative hits on the cache (null values), so use - this instead of calling t.GetInterfaces on the type everytime. - -2001-10-28 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (IsBuiltinType): New method to help determine the same. - - * expression.cs (New::DoResolve): Get rid of array creation code and instead - split functionality out into different classes. - - (New::FormArrayType): Move into NewBuiltinArray. - - (Invocation::EmitArguments): Get rid of the MethodBase argument. Appears - quite useless. - - (NewBuiltinArray): New class to handle creation of built-in arrays. - - (NewBuiltinArray::DoResolve): Implement guts of array creation. Also take into - account creation of one-dimensional arrays. - - (::Emit): Implement to use Newarr and Newobj opcodes accordingly. - - (NewUserdefinedArray::DoResolve): Implement. - - * cs-parser.jay (local_variable_type): Fix up to add the rank to the variable too. - - * typemanager.cs (AddModule): Used to add a ModuleBuilder to the list of modules - we maintain inside the TypeManager. This is necessary to perform lookups on the - module builder. - - (LookupType): Update to perform GetType on the module builders too. - - * driver.cs (Driver): Add the ModuleBuilder to the list maintained by the TypeManager. - - * exprssion.cs (NewUserdefinedArray::Emit): Implement. - -2001-10-23 Ravi Pratap <ravi@ximian.com> - - * expression.cs (New::DoResolve): Implement guts of array creation. - - (New::FormLookupType): Rename to FormArrayType and modify ever so slightly. - -2001-10-27 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Fix bug I introduced lsat night that broke - Delegates. - - (Expression.Resolve): Report a 246 error (can not resolve name) - if we find a SimpleName in the stream. - - (Expression.ResolveLValue): Ditto. - - (Expression.ResolveWithSimpleName): This function is a variant of - ResolveName, this one allows SimpleNames to be returned without a - warning. The only consumer of SimpleNames is MemberAccess - -2001-10-26 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Invocation::DoResolve): Catch SimpleNames that - might arrive here. I have my doubts that this is correct. - - * statement.cs (Lock): Implement lock statement. - - * cs-parser.jay: Small fixes to support `lock' and `using' - - * cs-tokenizer.cs: Remove extra space - - * driver.cs: New flag --checked, allows to turn on integer math - checking. - - * typemanger.cs: Load methodinfos for Threading.Monitor.Enter and - Threading.Monitor.Exit - -2001-10-23 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (IndexerAccess::DoResolveLValue): Set the - Expression Class to be IndexerAccess. - - Notice that Indexer::DoResolve sets the eclass to Value. - -2001-10-22 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer::Emit): Emit code for indexers. - - * assign.cs (IAssignMethod): New interface implemented by Indexers - and Properties for handling assignment. - - (Assign::Emit): Simplify and reuse code. - - * expression.cs (IndexerAccess, PropertyExpr): Implement - IAssignMethod, clean up old code. - -2001-10-22 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (ImplementsInterface): New method to determine if a type - implements a given interface. Provides a nice cache too. - - * expression.cs (ImplicitReferenceConversion): Update checks to use the above - method. - - (ConvertReferenceExplicit): Ditto. - - * delegate.cs (Delegate::Populate): Update to define the parameters on the - various methods, with correct names etc. - - * class.cs (Operator::OpType): New members Operator.UnaryPlus and - Operator.UnaryNegation. - - * cs-parser.jay (operator_declarator): Be a little clever in the case where - we have a unary plus or minus operator. - - * expression.cs (Unary): Rename memebers of Operator enum to UnaryPlus and - UnaryMinus. - - * everywhere : update accordingly. - - * everywhere : Change Negate and BitComplement to LogicalNot and OnesComplement - respectively. - - * class.cs (Method::Define): For the case where we are implementing a method - inherited from an interface, we need to set the MethodAttributes.Final flag too. - Also set MethodAttributes.NewSlot and MethodAttributes.HideBySig. - -2001-10-21 Ravi Pratap <ravi@ximian.com> - - * interface.cs (FindMembers): Implement to work around S.R.E - lameness. - - * typemanager.cs (IsInterfaceType): Implement. - - (FindMembers): Update to handle interface types too. - - * expression.cs (ImplicitReferenceConversion): Re-write bits which - use IsAssignableFrom as that is not correct - it doesn't work. - - * delegate.cs (DelegateInvocation): Derive from ExpressionStatement - and accordingly override EmitStatement. - - * expression.cs (ConvertReferenceExplicit): Re-write similary, this time - using the correct logic :-) - -2001-10-19 Ravi Pratap <ravi@ximian.com> - - * ../errors/cs-11.cs : Add to demonstrate error -11 - -2001-10-17 Miguel de Icaza <miguel@ximian.com> - - * assign.cs (Assign::Resolve): Resolve right hand side first, and - then pass this as a hint to ResolveLValue. - - * expression.cs (FieldExpr): Add Location information - - (FieldExpr::LValueResolve): Report assignment to readonly - variable. - - (Expression::ExprClassFromMemberInfo): Pass location information. - - (Expression::ResolveLValue): Add new method that resolves an - LValue. - - (Expression::DoResolveLValue): Default invocation calls - DoResolve. - - (Indexers): New class used to keep track of indexers in a given - Type. - - (IStackStore): Renamed from LValue, as it did not really describe - what this did. Also ResolveLValue is gone from this interface and - now is part of Expression. - - (ElementAccess): Depending on the element access type - - * typemanager.cs: Add `indexer_name_type' as a Core type - (System.Runtime.CompilerServices.IndexerNameAttribute) - - * statement.cs (Goto): Take a location. - -2001-10-18 Ravi Pratap <ravi@ximian.com> - - * delegate.cs (Delegate::VerifyDelegate): New method to verify - if two delegates are compatible. - - (NewDelegate::DoResolve): Update to take care of the case when - we instantiate a delegate from another delegate. - - * typemanager.cs (FindMembers): Don't even try to look up members - of Delegate types for now. - -2001-10-18 Ravi Pratap <ravi@ximian.com> - - * delegate.cs (NewDelegate): New class to take care of delegate - instantiation. - - * expression.cs (New): Split the delegate related code out into - the NewDelegate class. - - * delegate.cs (DelegateInvocation): New class to handle delegate - invocation. - - * expression.cs (Invocation): Split out delegate related code into - the DelegateInvocation class. - -2001-10-17 Ravi Pratap <ravi@ximian.com> - - * expression.cs (New::DoResolve): Implement delegate creation fully - and according to the spec. - - (New::DoEmit): Update to handle delegates differently. - - (Invocation::FullMethodDesc): Fix major stupid bug thanks to me - because of which we were printing out arguments in reverse order ! - - * delegate.cs (VerifyMethod): Implement to check if the given method - matches the delegate. - - (FullDelegateDesc): Implement. - - (VerifyApplicability): Implement. - - * expression.cs (Invocation::DoResolve): Update to accordingly handle - delegate invocations too. - - (Invocation::Emit): Ditto. - - * ../errors/cs1593.cs : Added. - - * ../errors/cs1594.cs : Added. - - * delegate.cs (InstanceExpression, TargetMethod): New properties. - -2001-10-16 Ravi Pratap <ravi@ximian.com> - - * typemanager.cs (intptr_type): Core type for System.IntPtr - - (InitCoreTypes): Update for the same. - - (iasyncresult_type, asynccallback_type): Ditto. - - * delegate.cs (Populate): Fix to use System.Intptr as it is indeed - correct. - - * typemanager.cs (AddDelegateType): Store a pointer to the Delegate class - too. - - * delegate.cs (ConstructorBuilder, InvokeBuilder, ...): New members to hold - the builders for the 4 members of a delegate type :-) - - (Populate): Define the BeginInvoke and EndInvoke methods on the delegate - type. - - * expression.cs (New::DoResolve): Implement guts for delegate creation. - - * ../errors/errors.txt : Update for an error (-11) which only we catch :-) - -2001-10-15 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Break::Emit): Implement. - (Continue::Emit): Implement. - - (For::Emit): Track old being/end loops; Set Begin loop, ack end loop - (While::Emit): Track old being/end loops; Set Begin loop, ack end loop - (Do::Emit): Track old being/end loops; Set Begin loop, ack end loop - (Foreach::Emit): Track old being/end loops; Set Begin loop, ack - end loop - - * codegen.cs (EmitContext::LoopEnd, EmitContext::LoopBegin): New - properties that track the label for the current loop (begin of the - loop and end of the loop). - -2001-10-15 Ravi Pratap <ravi@ximian.com> - - * delegate.cs (Emit): Get rid of it as there doesn't seem to be any ostensible - use of emitting anything at all. - - * class.cs, rootcontext.cs : Get rid of calls to the same. - - * delegate.cs (DefineDelegate): Make sure the class we define is also sealed. - - (Populate): Define the constructor correctly and set the implementation - attributes. - - * typemanager.cs (delegate_types): New hashtable to hold delegates that - have been defined. - - (AddDelegateType): Implement. - - (IsDelegateType): Implement helper method. - - * delegate.cs (DefineDelegate): Use AddDelegateType instead of AddUserType. - - * expression.cs (New::DoResolve): Check if we are trying to instantiate a delegate type - and accordingly handle it. - - * delegate.cs (Populate): Take TypeContainer argument. - Implement bits to define the Invoke method. However, I still haven't figured out - how to take care of the native int bit :-( - - * cs-parser.jay (delegate_declaration): Fixed the bug that I had introduced :-) - Qualify the name of the delegate, not its return type ! - - * expression.cs (ImplicitReferenceConversion): Implement guts of implicit array - conversion. - - (StandardConversionExists): Checking for array types turns out to be recursive. - - (ConvertReferenceExplicit): Implement array conversion. - - (ExplicitReferenceConversionExists): New method to determine precisely that :-) - -2001-10-12 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (delegate_declaration): Store the fully qualified - name as it is a type declaration. - - * delegate.cs (ReturnType, Name): Rename members to these. Make them - readonly. - - (DefineDelegate): Renamed from Define. Does the same thing essentially, - as TypeContainer::DefineType. - - (Populate): Method in which all the definition of the various methods (Invoke) - etc is done. - - (Emit): Emit any code, if necessary. I am not sure about this really, but let's - see. - - (CloseDelegate): Finally creates the delegate. - - * class.cs (TypeContainer::DefineType): Update to define delegates. - (Populate, Emit and CloseType): Do the same thing here too. - - * rootcontext.cs (ResolveTree, PopulateTypes, EmitCode, CloseTypes): Include - delegates in all these operations. - -2001-10-14 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: LocalTemporary: a new expression used to - reference a temporary that has been created. - - * assign.cs: Handle PropertyAccess back here, so that we can - provide the proper semantic access to properties. - - * expression.cs (Expression::ConvertReferenceExplicit): Implement - a few more explicit conversions. - - * modifiers.cs: `NEW' modifier maps to HideBySig. - - * expression.cs (PropertyExpr): Make this into an - ExpressionStatement, and support the EmitStatement code path. - - Perform get/set error checking, clean up the interface. - - * assign.cs: recognize PropertyExprs as targets, and if so, turn - them into toplevel access objects. - -2001-10-12 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: PropertyExpr::PropertyExpr: use work around the - SRE. - - * typemanager.cs: Keep track here of our PropertyBuilders again to - work around lameness in SRE. - -2001-10-11 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (LValue::LValueResolve): New method in the - interface, used to perform a second resolution pass for LValues. - - (This::DoResolve): Catch the use of this in static methods. - - (This::LValueResolve): Implement. - - (This::Store): Remove warning, assigning to `this' in structures - is - - (Invocation::Emit): Deal with invocation of - methods on value types. We need to pass the address to structure - methods rather than the object itself. (The equivalent code to - emit "this" for structures leaves the entire structure on the - stack instead of a pointer to it). - - (ParameterReference::DoResolve): Compute the real index for the - argument based on whether the method takes or not a `this' pointer - (ie, the method is static). - - * codegen.cs (EmitContext::GetTemporaryStorage): Used to store - value types returned from functions when we need to invoke a - method on the sturcture. - - -2001-10-11 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::DefineType): Method to actually do the business of - defining the type in the Modulebuilder or Typebuilder. This is to take - care of nested types which need to be defined on the TypeBuilder using - DefineNestedMethod. - - (TypeContainer::GetClassBases): Implement. Essentially the code from the - methods in RootContext, only ported to be part of TypeContainer. - - (TypeContainer::GetInterfaceOrClass): Ditto. - - (TypeContainer::LookupInterfaceOrClass, ::MakeFQN): Ditto. - - * interface.cs (Interface::DefineInterface): New method. Does exactly - what RootContext.CreateInterface did earlier, only it takes care of nested types - too. - - (Interface::GetInterfaces): Move from RootContext here and port. - - (Interface::GetInterfaceByName): Same here. - - * rootcontext.cs (ResolveTree): Re-write. - - (PopulateTypes): Re-write. - - * class.cs (TypeContainer::Populate): Populate nested types too. - (TypeContainer::Emit): Emit nested members too. - - * typemanager.cs (AddUserType): Do not make use of the FullName property, - instead just use the name argument passed in as it is already fully - qualified. - - (FindMembers): Check in the Builders to TypeContainer mapping instead of the name - to TypeContainer mapping to see if a type is user-defined. - - * class.cs (TypeContainer::CloseType): Implement. - - (TypeContainer::DefineDefaultConstructor): Use Basename, not Name while creating - the default constructor. - - (TypeContainer::Populate): Fix minor bug which led to creating default constructors - twice. - - (Constructor::IsDefault): Fix up logic to determine if it is the default constructor - - * interface.cs (CloseType): Create the type here. - - * rootcontext.cs (CloseTypes): Re-write to recursively close types by running through - the hierarchy. - - Remove all the methods which are now in TypeContainer. - -2001-10-10 Ravi Pratap <ravi@ximian.com> - - * delegate.cs (Define): Re-write bits to define the delegate - correctly. - -2001-10-10 Miguel de Icaza <miguel@ximian.com> - - * makefile: Renamed the compiler to `mcs.exe' instead of compiler.exe - - * expression.cs (ImplicitReferenceConversion): handle null as well - as a source to convert to any reference type. - - * statement.cs (Return): Perform any implicit conversions to - expected return type. - - Validate use of return statement. - - * codegen.cs (EmitContext): Pass the expected return type here. - - * class.cs (Method, Constructor, Property): Pass expected return - type to EmitContext. - -2001-10-09 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Make DoResolve take an EmitContext instead of a - TypeContainer. - - Replaced `l' and `location' for `loc', for consistency. - - (Error, Warning): Remove unneeded Tc argument. - - * assign.cs, literal.cs, constant.cs: Update to new calling - convention. - - * codegen.cs: EmitContext now contains a flag indicating whether - code is being generated in a static method or not. - - * cs-parser.jay: DecomposeQI, new function that replaces the old - QualifiedIdentifier. Now we always decompose the assembled - strings from qualified_identifier productions into a group of - memberaccesses. - -2001-10-08 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs: Deal with field-less struct types correctly now - by passing the size option to Define Type. - - * class.cs: Removed hack that created one static field. - -2001-10-07 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: Moved most of the code generation here. - -2001-10-09 Ravi Pratap <ravi@ximian.com> - - * expression.cs (New::DoResolve): Revert changes for array creation, doesn't - seem very right. - - (ElementAccess): Remove useless bits for now - keep checks as the spec - says. - -2001-10-08 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ElementAccess::DoResolve): Remove my crap code - and start performing checks according to the spec. - -2001-10-07 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (type_suffix*): Remove - they are redundant. Use - rank_specifiers instead. - - (rank_specifiers): Change the order in which the rank specifiers are stored - - (local_variable_declaration): Use opt_rank_specifier instead of type_suffixes. - - * expression.cs (ElementAccess): Implement the LValue interface too. - -2001-10-06 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ConvertExplicitStandard): Add. Same as ConvertExplicit - except that user defined conversions are not included. - - (UserDefinedConversion): Update to use the ConvertExplicitStandard to - perform the conversion of the return type, if necessary. - - (New::DoResolve): Check whether we are creating an array or an object - and accordingly do the needful. - - (New::Emit): Same here. - - (New::DoResolve): Implement guts of array creation. - - (New::FormLookupType): Helper function. - -2001-10-07 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs: Removed most of the code generation here, and move the - corresponding code generation bits to the statement classes. - - Added support for try/catch/finalize and throw. - - * cs-parser.jay: Added support for try/catch/finalize. - - * class.cs: Catch static methods having the flags override, - virtual or abstract. - - * expression.cs (UserCast): This user cast was not really doing - what it was supposed to do. Which is to be born in fully resolved - state. Parts of the resolution were being performed at Emit time! - - Fixed this code. - -2001-10-05 Miguel de Icaza <miguel@ximian.com> - - * expression.cs: Implicity convert the result from UserCast. - -2001-10-05 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Expression::FindMostEncompassingType): Fix bug which - prevented it from working correctly. - - (ConvertExplicit): Make the first try, a call to ConvertImplicitStandard, not - merely ConvertImplicit. - -2001-10-05 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs: Make the LookupTypeContainer function static, - and not per-instance. - - * class.cs: Make static FindMembers (the one that takes a Type - argument). - - * codegen.cs: Add EmitForeach here. - - * cs-parser.jay: Make foreach a toplevel object instead of the - inline expansion, as we need to perform semantic analysis on it. - -2001-10-05 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Expression::ImplicitUserConversion): Rename to - UserDefinedConversion. - - (Expression::UserDefinedConversion): Take an extra argument specifying - whether we look for explicit user conversions too. - - (Expression::ImplicitUserConversion): Make it a call to UserDefinedConversion. - - (UserDefinedConversion): Incorporate support for user defined explicit conversions. - - (ExplicitUserConversion): Make it a call to UserDefinedConversion - with the appropriate arguments. - - * cs-parser.jay (cast_expression): Record location too. - - * expression.cs (Cast): Record location info. - - (Expression::ConvertExplicit): Take location argument. - - (UserImplicitCast): Change name to UserCast. Take an extra constructor argument - to determine if we are doing explicit conversions. - - (UserCast::Emit): Update accordingly. - - (Expression::ConvertExplicit): Report an error if everything fails. - - * ../errors/cs0030.cs : Add. - -2001-10-04 Miguel de Icaza <miguel@ximian.com> - - * modifiers.cs: If the ABSTRACT keyword is present, also set the - virtual and newslot bits. - - * class.cs (TypeContainer::RegisterRequiredImplementations): - Record methods we need. - - (TypeContainer::MakeKey): Helper function to make keys for - MethodBases, since the Methodbase key is useless. - - (TypeContainer::Populate): Call RegisterRequiredImplementations - before defining the methods. - - Create a mapping for method_builders_to_methods ahead of time - instead of inside a tight loop. - - (::RequireMethods): Accept an object as the data to set into the - hashtable so we can report interface vs abstract method mismatch. - -2001-10-03 Miguel de Icaza <miguel@ximian.com> - - * report.cs: Make all of it static. - - * rootcontext.cs: Drop object_type and value_type computations, as - we have those in the TypeManager anyways. - - Drop report instance variable too, now it is a global. - - * driver.cs: Use try/catch on command line handling. - - Add --probe option to debug the error reporting system with a test - suite. - - * report.cs: Add support for exiting program when a probe - condition is reached. - -2001-10-03 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Binary::DoNumericPromotions): Fix the case when - we do a forcible conversion regardless of type, to check if - ForceConversion returns a null. - - (Binary::error19): Use location to report error. - - (Unary::error23): Use location here too. - - * ../errors/cs0019.cs : Check in. - - * ../errors/cs0023.cs : Check in. - - * expression.cs (Expression.MemberLookup): Return null for a rather esoteric - case of a non-null MethodInfo object with a length of 0 ! - - (Binary::ResolveOperator): Flag error if overload resolution fails to find - an applicable member - according to the spec :-) - Also fix logic to find members in base types. - - (Unary::ResolveOperator): Same here. - - (Unary::report23): Change name to error23 and make first argument a TypeContainer - as I was getting thoroughly confused between this and error19 :-) - - * expression.cs (Expression::ImplicitUserConversion): Re-write fully - (::FindMostEncompassedType): Implement. - (::FindMostEncompassingType): Implement. - (::StandardConversionExists): Implement. - - (UserImplicitCast): Re-vamp. We now need info about most specific - source and target types so that we can do the necessary conversions. - - (Invocation::MakeUnionSet): Completely re-write to make sure we form a proper - mathematical union with no duplicates. - -2001-10-03 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs (RootContext::PopulateTypes): Populate containers - in order from base classes to child classes, so that we can in - child classes look up in our parent for method names and - attributes (required for handling abstract, virtual, new, override - constructs: we need to instrospect our base class, and if we dont - populate the classes in order, the introspection might be - incorrect. For example, a method could query its parent before - the parent has any methods and would determine that the parent has - no abstract methods (while it could have had them)). - - (RootContext::CreateType): Record the order in which we define the - classes. - -2001-10-02 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer::Populate): Also method definitions can - fail now, keep track of this. - - (TypeContainer::FindMembers): Implement support for - DeclaredOnly/noDeclaredOnly flag. - - (Constructor::Emit) Return the ConstructorBuilder. - - (Method::Emit) Return the MethodBuilder. - Check for abstract or virtual methods to be public. - - * rootcontext.cs (RootContext::CreateType): Register all the - abstract methods required for the class to be complete and the - interface methods that must be implemented. - - * cs-parser.jay: Report error 501 (method requires body if it is - not marked abstract or extern). - - * expression.cs (TypeOf::Emit): Implement. - - * typemanager.cs: runtime_handle_type, new global type. - - * class.cs (Property::Emit): Generate code for properties. - -2001-10-02 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Unary::ResolveOperator): Find operators on base type - too - we now conform exactly to the spec. - - (Binary::ResolveOperator): Same here. - - * class.cs (Operator::Define): Fix minor quirk in the tests. - - * ../errors/cs0215.cs : Added. - - * ../errors/cs0556.cs : Added. - - * ../errors/cs0555.cs : Added. - -2001-10-01 Miguel de Icaza <miguel@ximian.com> - - * cs-tokenizer.cs: Reimplemented Location to be a struct with a - single integer which is really efficient - -2001-10-01 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Expression::ImplicitUserConversion): Use location - even in the case when we are examining True operators. - - * class.cs (Operator::Define): Perform extensive checks to conform - with the rules for operator overloading in the spec. - - * expression.cs (Expression::ImplicitReferenceConversion): Implement - some of the other conversions mentioned in the spec. - - * typemanager.cs (array_type): New static member for the System.Array built-in - type. - - (cloneable_interface): For System.ICloneable interface. - - * driver.cs (Driver::Driver): Initialize TypeManager's core types even before - we start resolving the tree and populating types. - - * ../errors/errors.txt : Update for error numbers -7, -8, -9, -10 - -2001-10-01 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Expression::ExprClassFromMemberInfo, - Expression::Literalize): Create literal expressions from - FieldInfos which are literals. - - (ConvertNumericExplicit, ImplicitNumericConversion): Fix a few - type casts, because they were wrong. The test suite in tests - caught these ones. - - (ImplicitNumericConversion): ushort to ulong requires a widening - cast. - - Int32 constant to long requires widening cast as well. - - * literal.cs (LongLiteral::EmitLong): Do not generate i4 constants - for integers because the type on the stack is not i4. - -2001-09-30 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (report118): require location argument. - - * parameter.cs: Do not dereference potential null value. - - * class.cs: Catch methods that lack the `new' keyword when - overriding a name. Report warnings when `new' is used without - anything being there to override. - - * modifiers.cs: Handle `NEW' as MethodAttributes.NewSlot. - - * class.cs: Only add constructor to hashtable if it is non-null - (as now constructors can fail on define). - - (TypeManager, Class, Struct): Take location arguments. - - Catch field instance initialization in structs as errors. - - accepting_filter: a new filter for FindMembers that is static so - that we dont create an instance per invocation. - - (Constructor::Define): Catch errors where a struct constructor is - parameterless - - * cs-parser.jay: Pass location information for various new - constructs. - - * delegate.cs (Delegate): take a location argument. - - * driver.cs: Do not call EmitCode if there were problesm in the - Definition of the types, as many Builders wont be there. - - * decl.cs (Decl::Decl): Require a location argument. - - * cs-tokenizer.cs: Handle properly hex constants that can not fit - into integers, and find the most appropiate integer for it. - - * literal.cs: Implement ULongLiteral. - - * rootcontext.cs: Provide better information about the location of - failure when CreateType fails. - -2001-09-29 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs (RootContext::PopulateTypes): Populates structs - as well. - - * expression.cs (Binary::CheckShiftArguments): Add missing type - computation. - (Binary::ResolveOperator): Add type to the logical and and logical - or, Bitwise And/Or and Exclusive Or code paths, it was missing - before. - - (Binary::DoNumericPromotions): In the case where either argument - is ulong (and most signed types combined with ulong cause an - error) perform implicit integer constant conversions as well. - -2001-09-28 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (UserImplicitCast): Method should always be - non-null. - (Invocation::BetterConversion): Simplified test for IntLiteral. - - (Expression::ImplicitNumericConversion): Split this routine out. - Put the code that performs implicit constant integer conversions - here. - - (Expression::Resolve): Become a wrapper around DoResolve so we can - check eclass and type being set after resolve. - - (Invocation::Badness): Remove this dead function - - (Binary::ResolveOperator): Do not compute the expensive argumnets - unless we have a union for it. - - (Probe::Emit): Is needs to do an isinst and then - compare against null. - - (::CanConvert): Added Location argument. If the Location argument - is null (Location.Null), then we do not report errors. This is - used by the `probe' mechanism of the Explicit conversion. We do - not want to generate an error for something that the user - explicitly requested to be casted. But the pipeline for an - explicit cast first tests for potential implicit casts. - - So for now, if the Location is null, it means `Probe only' to - avoid adding another argument. Might have to revise this - strategy later. - - (ClassCast): New class used to type cast objects into arbitrary - classes (used in Explicit Reference Conversions). - - Implement `as' as well. - - Reverted all the patches from Ravi below: they were broken: - - * The use of `level' as a mechanism to stop recursive - invocations is wrong. That was there just to catch the - bug with a strack trace but not as a way of addressing - the problem. - - To fix the problem we have to *understand* what is going - on and the interactions and come up with a plan, not - just get things going. - - * The use of the type conversion cache that I proposed - last night had an open topic: How does this work across - protection domains. A user defined conversion might not - be public in the location where we are applying the - conversion, a different conversion might be selected - (ie, private A->B (better) but public B->A (worse), - inside A, A->B applies, but outside it, B->A will - apply). - - * On top of that (ie, even if the above is solved), - conversions in a cache need to be abstract. Ie, `To - convert from an Int to a Short use an OpcodeCast', not - `To convert from an Int to a Short use the OpcodeCast on - the variable 5' (which is what this patch was doing). - -2001-09-28 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation::ConversionExists): Re-write to use - the conversion cache - - (Expression::ConvertImplicit): Automatic bailing out if level != 0. Also - cache all conversions done, not just user-defined ones. - - (Invocation::BetterConversion): The real culprit. Use ConversionExists - to determine if a conversion exists instead of acutually trying to - perform the conversion. It's faster too. - - (Expression::ConvertExplicit): Modify to use ConversionExists to check - and only then attempt the implicit conversion. - -2001-09-28 Ravi Pratap <ravi@ximian.com> - - * expression.cs (ConvertImplicit): Use a cache for conversions - already found. Check level of recursion and bail out if necessary. - -2001-09-28 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (string_concat_string_string, string_concat_object_object): - Export standard methods that we expect for string operations. - - * statement.cs (Block::UsageWarning): Track usage of variables and - report the errors for not used variables. - - * expression.cs (Conditional::Resolve, ::Emit): Implement ?: - operator. - -2001-09-27 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs: remove unnneded code - - * expression.cs: Removed BuiltinTypeAccess class - - Fix the order in which implicit conversions are - done. - - The previous fixed dropped support for boxed conversions (adding a - test to the test suite now) - - (UserImplicitCast::CanConvert): Remove test for source being null, - that code is broken. We should not feed a null to begin with, if - we do, then we should track the bug where the problem originates - and not try to cover it up here. - - Return a resolved expression of type UserImplicitCast on success - rather than true/false. Ravi: this is what I was talking about, - the pattern is to use a static method as a "constructor" for - objects. - - Also, do not create arguments until the very last minute, - otherwise we always create the arguments even for lookups that - will never be performed. - - (UserImplicitCast::Resolve): Eliminate, objects of type - UserImplicitCast are born in a fully resolved state. - - * typemanager.cs (InitCoreTypes): Init also value_type - (System.ValueType). - - * expression.cs (Cast::Resolve): First resolve the child expression. - - (LValue): Add new method AddressOf to be used by - the `&' operator. - - Change the argument of Store to take an EmitContext instead of an - ILGenerator, because things like FieldExpr need to be able to call - their children expression to generate the instance code. - - (Expression::Error, Expression::Warning): Sugar functions for - reporting errors. - - (Expression::MemberLookup): Accept a TypeContainer instead of a - Report as the first argument. - - (Expression::ResolvePrimary): Killed. I still want to improve - this as currently the code is just not right. - - (Expression::ResolveMemberAccess): Simplify, but it is still - wrong. - - (Unary::Resolve): Catch errors in AddressOf operators. - - (LocalVariableReference::Emit, ::Store, ::AddressOf): typecast - index to a byte for the short-version, or the compiler will choose - the wrong Emit call, which generates the wrong data. - - (ParameterReference::Emit, ::Store): same. - - (FieldExpr::AddressOf): Implement. - - * typemanager.cs: TypeManager: made public variable instead of - property. - - * driver.cs: document --fatal. - - * report.cs (ErrorMessage, WarningMessage): new names for the old - Error and Warning classes. - - * cs-parser.jay (member_access): Turn built-in access to types - into a normal simplename - -2001-09-27 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation::BetterConversion): Fix to cope - with q being null, since this was introducing a bug. - - * expression.cs (ConvertImplicit): Do built-in conversions first. - -2001-09-27 Ravi Pratap <ravi@ximian.com> - - * expression.cs (UserImplicitCast::Resolve): Fix bug. - -2001-09-27 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::AddConstructor): Fix a stupid bug - I had introduced long ago (what's new ?). - - * expression.cs (UserImplicitCast::CanConvert): Static method to do - the work of all the checking. - (ConvertImplicit): Call CanConvert and only then create object if necessary. - (UserImplicitCast::CanConvert, ::Resolve): Re-write. - - (Unary::Operator): Rename Add and Subtract to Addition and Subtraction because - that is the right way. - - (Invocation::MakeUnionSet): Convenience function to make unions of sets for - overloading resolution. Use everywhere instead of cutting and pasting code. - - (Binary::ResolveOperator): Use MakeUnionSet. - - (UserImplicitCast::CanConvert, ::Resolve): Update to take care of the case when - we have to convert to bool types. Not complete yet. - -2001-09-27 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (TypeManager::CSharpName): support ushort. - - * expression.cs (Expression::TryImplicitIntConversion): Attempts - to provide an expression that performsn an implicit constant int - conversion (section 6.1.6). - (Expression::ConvertImplicitRequired): Reworked to include - implicit constant expression conversions. - - (Expression::ConvertNumericExplicit): Finished. - - (Invocation::Emit): If InstanceExpression is null, then it means - that we perform a call on this. - -2001-09-26 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Unary::Emit): Remove some dead code. - (Probe): Implement Resolve and Emit for `is'. - (Expression::ConvertImplicitRequired): Attempt to do constant - expression conversions here. Maybe should be moved to - ConvertImplicit, but I am not sure. - (Expression::ImplicitLongConstantConversionPossible, - Expression::ImplicitIntConstantConversionPossible): New functions - that tell whether is it possible to apply an implicit constant - expression conversion. - - (ConvertNumericExplicit): Started work on explicit numeric - conversions. - - * cs-parser.jay: Update operator constants. - - * parameter.cs (Parameters::GetParameterInfo): Hook up VerifyArgs - (Parameters::GetSignature): Hook up VerifyArgs here. - (Parameters::VerifyArgs): Verifies that no two arguments have the - same name. - - * class.cs (Operator): Update the operator names to reflect the - ones that the spec expects (as we are just stringizing the - operator names). - - * expression.cs (Unary::ResolveOperator): Fix bug: Use - MethodInfo's ReturnType instead of LookupMethodByBuilder as the - previous usage did only work for our methods. - (Expression::ConvertImplicit): Handle decimal implicit numeric - conversions as well. - (Expression::InternalTypeConstructor): Used to invoke constructors - on internal types for default promotions. - - (Unary::Emit): Implement special handling for the pre/post - increment/decrement for overloaded operators, as they need to have - the same semantics as the other operators. - - (Binary::ResolveOperator): ditto. - (Invocation::ConversionExists): ditto. - (UserImplicitCast::Resolve): ditto. - -2001-09-26 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Unary::Emit and Binary::Emit): If we have an overloaded - operator, return after emitting body. Regression tests pass again ! - - * expression.cs (ConvertImplicit): Take TypeContainer as first argument - (Unary::ForceConversion, Binary::ForceConversion): Ditto. - (Invocation::OverloadResolve): Ditto. - (Invocation::BetterFunction, BetterConversion, ConversionExists): Ditto. - - * everywhere : update calls to the above methods accordingly. - -2001-09-26 Miguel de Icaza <miguel@ximian.com> - - * assign.cs (Assign): Make it inherit from ExpressionStatement. - - * expression.cs (ExpressionStatement): New base class used for - expressions that can appear in statements, so that we can provide - an alternate path to generate expression that do not leave a value - on the stack. - - (Expression::Emit, and all the derivatives): We no longer return - whether a value is left on the stack or not. Every expression - after being emitted leaves a single value on the stack. - - * codegen.cs (EmitContext::EmitStatementExpression): Use the - facilties of ExpressionStatement if possible. - - * cs-parser.jay: Update statement_expression. - -2001-09-25 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Change the wording of message - -2001-09-25 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Binary::ResolveOperator): Had forgottten to set - the type of the expression to the return type of the method if - we have an overloaded operator match ! The regression tests pass again ! - (Unary::ResolveOperator): Ditto. - - * expression.cs (Invocation::ConversionExists): Correct the member lookup - to find "op_Implicit", not "implicit" ;-) - (UserImplicitCast): New class to take care of user-defined implicit conversions. - (ConvertImplicit, ForceConversion): Take TypeContainer argument - - * everywhere : Correct calls to the above accordingly. - - * expression.cs (UserImplicitCast::Resolve, ::Emit): Implement. - (ConvertImplicit): Do user-defined conversion if it exists. - -2001-09-24 Miguel de Icaza <miguel@ximian.com> - - * assign.cs: track location. - (Resolve): Use implicit conversions on assignment. - - * literal.cs: Oops. Not good, Emit of short access values should - pass (Bytes) or the wrong argument will be selected. - - * expression.cs (Unary::Emit): Emit code for -expr. - - (Unary::ResolveOperator): Handle `Substract' for non-constants - (substract from zero from the non-constants). - Deal with Doubles as well. - - (Expression::ConvertImplicitRequired): New routine that reports an - error if no implicit conversion exists. - - (Invocation::OverloadResolve): Store the converted implicit - expressions if we make them - -2001-09-24 Ravi Pratap <ravi@ximian.com> - - * class.cs (ConstructorInitializer): Take a Location argument. - (ConstructorBaseInitializer): Same here. - (ConstructorThisInitializer): Same here. - - * cs-parser.jay : Update all calls accordingly. - - * expression.cs (Unary, Binary, New): Take location argument. - Update accordingly everywhere. - - * cs-parser.jay : Update all calls to the above to take a location - argument. - - * class.cs : Ditto. - -2001-09-24 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation::BetterFunction): Take TypeContainer argument - (Invocation::BetterConversion): Same here - (Invocation::ConversionExists): Ditto. - - (Invocation::ConversionExists): Implement. - -2001-09-22 Ravi Pratap <ravi@ximian.com> - - * expression.cs (OverloadResolve): Improve some more to catch errors 1502 and 1503 - Also take an additional TypeContainer argument. - - * All over : Pass in TypeContainer as argument to OverloadResolve. - - * typemanager.cs (CSharpName): Update to check for the string type and return - that too. - - * expression.cs (Invocation::FullMethodDesc): New static method to return a string fully describing - a given method. - -2001-09-21 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Invocation::OverloadResolve): Re-write to conform more to the spec. - (Invocation::BetterFunction): Implement. - (Invocation::BetterConversion): Implement. - (Invocation::ConversionExists): Skeleton, no implementation yet. - - Okay, things work fine ! - -2001-09-21 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs: declare and load enum_type, delegate_type and - void_type. - - * expression.cs (Expression::Emit): Now emit returns a value that - tells whether a value is left on the stack or not. This strategy - might be reveted tomorrow with a mechanism that would address - multiple assignments. - (Expression::report118): Utility routine to report mismatches on - the ExprClass. - - (Unary::Report23): Report impossible type/operator combination - utility function. - - (Unary::IsIncrementableNumber): Whether the type can be - incremented or decremented with add. - (Unary::ResolveOperator): Also allow enumerations to be bitwise - complemented. - (Unary::ResolveOperator): Implement ++, !, ~, - - (Invocation::Emit): Deal with new Emit convetion. - - * All Expression derivatives: Updated their Emit method to return - whether they leave values on the stack or not. - - * codegen.cs (CodeGen::EmitStatement): Pop values left on the - stack for expressions that are statements. - -2001-09-20 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (LValue): New interface. Must be implemented by - LValue objects. - (LocalVariableReference, ParameterReference, FieldExpr): Implement - LValue interface. - - * assign.cs (Assign::Emit, Assign::Resolve): Use new LValue - interface for generating code, simplifies the code. - -2001-09-20 Ravi Pratap <ravi@ximian.com> - - * expression.cs (everywhere): Comment out return statements in ::Resolve - methods to avoid the warnings. - -2001-09-20 Miguel de Icaza <miguel@ximian.com> - - * driver.cs (parse): Report error 2001 if we can not open the - source file. - - * expression.cs (SimpleName::ResolveSimpleName): Error if we can - not resolve it. - - * cs-parser.jay (QualifierIdentifier): Pass location to SimpleName - object. - - * statement.cs (Block::EmitMeta): Reuse the count across all the variables, - otherwise nested blocks end up with the same index. - - * codegen.cs (CodeGen::EmitTopBlock): Pass initial sequence - - * expression.cs: Instead of having FIXMEs in the Resolve - functions, throw exceptions so it is obvious that we are facing a - bug. - - * cs-parser.jay (invocation_expression): Pass Location information. - - * codegen.cs (CodeGen::Save, CodeGen::CodeGen, CodeGen::Basename): - Use a basename for those routines because .NET does not like paths - on them. - - * class.cs (TypeContainer::AddMethod): Do not call DefineName if the name was - already defined. - -2001-09-19 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (TypeManager::CoreLookupType): A function to make sure that we - are loading the correct data types (throws an exception if not). - (TypeManager::InitCoreTypes): Use CoreLookupType - - * expression.cs (Unary::ResolveOperator): return the child - expression for expressions which are just +expr. - (Unary::ResolveOperator): Return negative literals for -LITERAL - expressions (otherwise they are Unary {Literal}). - (Invocation::Badness): Take into account `Implicit constant - expression conversions'. - - * literal.cs (LongLiteral): Implement long literal class. - (IntLiteral): export the `Value' of the intliteral. - -2001-09-19 Ravi Pratap <ravi@ximian.com> - - * expression.cs (Binary::Emit): Finally get the emission right ! Woo! - - * class.cs (Operator::Define): Change the methodname prefix to 'op_' - instead of 'Operator' - - * expression.cs (Binary::ResolveOperator): Update accordingly. - (Unary::Operator): Change names to 'Add' and 'Subtract' instead 'Plus' - and 'Minus' - - * cs-parser.jay (unary_expression): Update to use the new names. - - * gen-treedump.cs (GetUnary): Same here. - - * expression.cs (Unary::Resolve): Implement. - (Binary::ResolveOperator): Re-write bits to quietly continue if no overloaded - operators are found instead of making noise ;-) - (Unary::ResolveOperator): New method to do precisely the same thing which - Binary::ResolveOperator does for Binary expressions. - (Unary.method, .Arguments): Add. - (Unary::OperName): Implement. - (Unary::ForceConversion): Copy and Paste ! - - * class.cs (Operator::Define): Fix a small bug for the case when we have - a unary operator. - - * expression.cs (Unary::Emit): Implement. Need to find the right Opcodes - for the inbuilt operators. Only overloading works for now ;-) - -2001-09-18 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (CheckedExpr::Resolve, CheckedExpr::Emit, - UnCheckedExpr::Resolve, UnCheckedExpr::Emit): Implement. - - * expression.cs (This::Emit): Implement. - (This::Resolve): Implement. - (TypeOf:Resolve): Implement. - (Expression::ResolveSimpleName): Add an implicit this to instance - field references. - (MemberAccess::Resolve): Deal with Parameters and Fields. - Bind instance variable to Field expressions. - (FieldExpr::Instance): New field used to track the expression that - represents the object instance. - (FieldExpr::Resolve): Track potential errors from MemberLookup not - binding - (FieldExpr::Emit): Implement. - - * codegen.cs (EmitIf, EmitStatement, EmitBlock): Propagate whether - the last instruction contains a return opcode to avoid generating - the last `ret' instruction (this generates correct code, and it is - nice to pass the peverify output). - - * class.cs (TypeContainer::EmitFieldInitializers): Implement field - initializer for static and instance variables. - (Constructor::Emit): Allow initializer to be null in the case of - static constructors. Only emit initializer for instance - constructors. - - (TypeContainer::FindMembers): Return a null array if there are no - matches. - - Also fix the code for the MemberTypes.Method branch, as it was not - scanning that for operators (or tried to access null variables before). - - * assign.cs (Assign::Emit): Handle instance and static fields. - - * TODO: Updated. - - * driver.cs: Stop compilation if there are parse errors. - - * cs-parser.jay (constructor_declaration): Provide default base - initializer for non-static constructors. - (constructor_declarator): Do not provide a default base - initializers if none was specified. - Catch the fact that constructors should not have parameters. - - * class.cs: Do not emit parent class initializers for static - constructors, that should be flagged as an error. - -2001-09-18 Ravi Pratap <ravi@ximian.com> - - * class.cs (RegisterMethodBuilder): Remove : it's unnecessary. - Move back code into TypeContainer::Populate. - -2001-09-18 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::AddConstructor): Fix the check to - compare against Name, not Basename. - (Operator::OpType): Change Plus and Minus to Add and Subtract. - - * cs-parser.jay : Update accordingly. - - * class.cs (TypeContainer::FindMembers): For the case where we are searching - for methods, don't forget to look into the operators too. - (RegisterMethodBuilder): Helper method to take care of this for - methods, constructors and operators. - (Operator::Define): Completely revamp. - (Operator.OperatorMethod, MethodName): New fields. - (TypeContainer::Populate): Move the registering of builders into - RegisterMethodBuilder. - (Operator::Emit): Re-write. - - * expression.cs (Binary::Emit): Comment out code path to emit method - invocation stuff for the case when we have a user defined operator. I am - just not able to get it right ! - -2001-09-17 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Expression::OverloadResolve): Drop TypeContainer - argument. - - (Expression::MemberLookup): Provide a version that allows to - specify the MemberTypes and BindingFlags. - - * statement.cs (Block::GetVariableInfo): Forgot to recurse here, - so it was not fetching variable information from outer blocks. - - * modifiers.cs: (Modifiers::TypeAttr): Invert condition on - Beforefieldinit as it was buggy. - - * rootcontext.cs (::LookupInterfaceOrClass): Removed an Error -200 - that Ravi put here. - - * class.cs (Constructor::Emit): Only emit if block is not null. - (TypeContainer::EmitDefaultConstructor): Removed routine, now we - deal with this by semantically definining it as if the user had - done it. - - (TypeContainer::FindMembers): Removed ad-hoc hack to deal with - constructors as we now "emit" them at a higher level. - - (TypeContainer::DefineDefaultConstructor): Used to define the - default constructors if none was provided. - - (ConstructorInitializer): Add methods Resolve and Emit. - - * expression.cs: Cast to ConstructorInfo instead of MethodInfo - -2001-09-17 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::EmitDefaultConstructor): Register - the default constructor builder with our hashtable for methodbuilders - to methodcores. - - * expression.cs (Invocation::OverloadResolve): Add a check for pd == null - and argument_count is 0 in which case we have a match. - (Binary::ResolveOperator): More null checking and miscellaneous coding - style cleanup. - -2001-09-17 Ravi Pratap <ravi@ximian.com> - - * rootcontext.cs (IsNameSpace): Compare against null. - - * everywhere : Correct spelling to 'Greater' and to 'Subtract' - - * class.cs (Operator::OpType): Change names to match the ones in Binary::Operator - and Unary::Operator. - - * cs-parser.jay (operator_declaration, CheckBinaryOperator, CheckUnaryOperator): Update - accordingly. - - * expression.cs (Binary::method): New member to hold the MethodBase for the case when - we have overloaded operators. - (Binary::ResolveOperator): Implement the part which does the operator overload - resolution. - - * class.cs (Operator::Emit): Implement. - (TypeContainer::Emit): Emit the operators we have too. - - * expression.cs (Binary::Emit): Update to emit the appropriate code for - the case when we have a user-defined operator. - -2001-09-17 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs: Fix bug: tree.Namespaces might be null. - -2001-09-16 Ravi Pratap <ravi@ximian.com> - - * class.cs (EmitStaticFieldInitializers, EmitFieldInitializers): Make public. - (TypeContainer::EmitConstructor): Remove and move code into Contructor::Emit. - (Constructor::Emit): Implement. - (EmitStaticFieldInitializers, EmitFieldInitializers): Ensure we return immediately - if we have no work to do. - (TypeContainer::Emit): Pass in TypeContainer as argument to the constructor's - Emit method. - - * interface.cs (Interface::InterfaceAttr): Re-write to be more correct and complete. - (Interface::IsTopLevel): Add. Same as TypeContainer::IsTopLevel. - - * class.cs (TypeContainer::IsTopLevel): Modify to use parent.Parent instead - of parent.parent. - -2001-09-15 Ravi Pratap <ravi@ximian.com> - - * tree.cs (Tree::namespaces): New hashtable to keep track of namespaces - in the source. - (Tree::RecordNamespace): Method to do what the name says ;-) - (Tree::Namespaces): Property to get at the namespaces hashtable. - - * cs-parser.jay (namespace_declaration): Call RecordNamespace to - keep track. - - * rootcontext.cs (IsNamespace): Fixed it :-) - -2001-09-14 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer::FindMembers): Add support for - constructors. - (MethodCore): New class that encapsulates both the shared aspects - of a Constructor and a Method. - (Method, Constructor): Factored pieces into MethodCore. - - * driver.cs: Added --fatal which makes errors throw exceptions. - Load System assembly as well as part of the standard library. - - * report.cs: Allow throwing exceptions on errors for debugging. - - * modifiers.cs: Do not use `parent', instead use the real type - container to evaluate permission settings. - - * class.cs: Put Ravi's patch back in. He is right, and we will - have to cope with the - -2001-09-14 Ravi Pratap <ravi@ximian.com> - - * modifiers.cs (TypeAttr, MethodAttr, FieldAttr): Map protected internal to - FamORAssem, not FamANDAssem. - -2001-09-14 Miguel de Icaza <miguel@ximian.com> - - * driver.cs: Added --parse option that only parses its input files - and terminates. - - * class.cs: Reverted last change from Ravi to IsTopLevel. That is - incorrect. IsTopLevel is not used to tell whether an object is - root_types or not (that can be achieved by testing this == - root_types). But to see if this is a top-level *class* (not - necessarly our "toplevel" container). - -2001-09-14 Ravi Pratap <ravi@ximian.com> - - * enum.cs (Enum::Define): Modify to call the Lookup method on the - parent instead of a direct call to GetType. - -2001-09-14 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::TypeAttr): Remove property code and move it into - Modifiers.TypeAttr. This should just be a call to that method. - - * modifiers.cs (TypeAttr): Re-write and take an extra argument, the TypeContainer - object so that we can determine if we are top-level or not. - - * delegate.cs (Delegate::Define): Update call to TypeAttr method to pass in the - TypeContainer too. - - * enum.cs (Enum::Define): Ditto. - - * modifiers.cs (FieldAttr): Re-write. - - * class.cs (TypeContainer::IsTopLevel): Change accessibility to public. - (TypeContainer::HaveStaticConstructor): New property to provide access - to precisely that info. - - * modifiers.cs (MethodAttr): Re-write. - (EventAttr): Remove altogether as there seems to be no ostensible use for it. - - * class.cs (TypeContainer::IsTopLevel): Re-write. root_types doesn't seem to be the parent - of top-level types as claimed. - -2001-09-13 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (MemberLookup): Fruitless attempt to lookup - constructors. Maybe I need to emit default constructors? That - might be it (currently .NET emits this for me automatically). - (Invocation::OverloadResolve): Cope with Arguments == null. - (Invocation::EmitArguments): new function, shared by the new - constructor and us. - (Invocation::Emit): Handle static and instance methods. Emit - proper call instruction for virtual or non-virtual invocations. - (New::Emit): Implement. - (New::Resolve): Implement. - (MemberAccess:Resolve): Implement. - (MethodGroupExpr::InstanceExpression): used conforming to the spec - to track instances. - (FieldExpr::Resolve): Set type. - - * support.cs: Handle empty arguments. - - * cs-parser.jay (CompositeLookup, QualifierIdentifier, - SimpleLookup): Auxiliary routines to help parse a qualifier - identifier. - - Update qualifier_identifier rule. - - * codegen.cs: Removed debugging messages. - - * class.cs: Make this a global thing, this acts just as a "key" to - objects that we might have around. - - (Populate): Only initialize method_builders_to_methods once. - - * expression.cs (PropertyExpr): Initialize type from the - PropertyType. - - * codegen.cs (EmitContext::EmitBoolExpression): Use propper - Resolve pattern. Attempt to implicitly convert value to boolean. - Emit code. - - * expression.cs: Set the type for the int32/int32 argument case. - (Binary::ResolveOperator): Set the return type to boolean for - comparission operators - - * typemanager.cs: Remove debugging print code. - - (Invocation::Resolve): resolve type. - - * class.cs: Allocate a MemberInfo of the correct size, as the code - elsewhere depends on the test to reflect the correct contents. - - (Method::) Keep track of parameters, due to System.Reflection holes - - (TypeContainer::Populate): Keep track of MethodBuilders to Method - mapping here. - - (TypeContainer::FindMembers): Use ArrayList and then copy an array - of the exact size and return that. - - (Class::LookupMethodByBuilder): New function that maps - MethodBuilders to its methods. Required to locate the information - on methods because System.Reflection bit us again. - - * support.cs: New file, contains an interface ParameterData and - two implementations: ReflectionParameters and InternalParameters - used to access Parameter information. We will need to grow this - as required. - - * expression.cs (Invocation::GetParameterData): implement a cache - and a wrapper around the ParameterData creation for methods. - (Invocation::OverloadResolve): Use new code. - -2001-09-13 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::EmitField): Remove and move into - (Field::Define): here and modify accordingly. - (Field.FieldBuilder): New member. - (TypeContainer::Populate): Update accordingly. - (TypeContainer::FindMembers): Implement. - -2001-09-13 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: (VariableInfo::VariableType): New field to be - initialized with the full type once it is resolved. - -2001-09-12 Miguel de Icaza <miguel@ximian.com> - - * parameter.cs (GetParameterInfo): Use a type cache to compute - things only once, and to reuse this information - - * expression.cs (LocalVariableReference::Emit): Implement. - (OpcodeCast::Emit): fix. - - (ParameterReference::Resolve): Implement. - (ParameterReference::Emit): Implement. - - * cs-parser.jay: Fix bug introduced by Ravi, variable initializers - that are expressions need to stay as Expressions. - - * typemanager.cs (CSharpName): Returns the C# name of a type if - possible. - - * expression.cs (Expression::ConvertImplicit): New function that - implements implicit type conversions. - - (Expression::ImplicitReferenceConversion): Implements implicit - reference conversions. - - (EmptyCast): New type for transparent casts. - - (OpcodeCast): New type for casts of types that are performed with - a sequence of bytecodes. - - (BoxedCast): New type used for casting value types into reference - types. Emits a box opcode. - - (Binary::DoNumericPromotions): Implements numeric promotions of - and computation of the Binary::Type. - - (Binary::EmitBranchable): Optimization. - - (Binary::Emit): Implement code emission for expressions. - - * typemanager.cs (TypeManager): Added two new core types: sbyte - and byte. - -2001-09-12 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::FindMembers): Method which does exactly - what Type.FindMembers does, only we don't have to use reflection. No - implementation yet. - - * typemanager.cs (typecontainers): New hashtable to hold the corresponding - typecontainer objects as we need to get at them. - (TypeManager::AddUserType): Overload to take an extra argument, the TypeContainer. - - * rootcontext.cs : Correspondingly modify called to AddUserType to pass the - typecontainer object. - - * expression.cs (MemberLookup): Modify signature to take a RootContext object instead - of just a Report object. - -2001-09-11 Ravi Pratap <ravi@ximian.com> - - * class.cs (Event::Define): Go back to using the prefixes "add_" and - "remove_" - (TypeContainer::Populate): Now define the delegates of the type too. - (TypeContainer.Delegates): Property to access the list of delegates defined - in the type. - - * delegates.cs (Delegate::Define): Implement partially. - - * modifiers.cs (TypeAttr): Handle more flags. - -2001-09-11 Ravi Pratap <ravi@ximian.com> - - * class.cs (Indexer::Define): Fix for loop iteration condition to be just < - and not <= - (Operator::Define): Re-write logic to get types by using the LookupType method - instead of blindly doing a Type.GetType ! How stupid can I get ;-) ? - (Indexer::Define): Ditto. - (Event::Define): Ditto. - (Property::Define): Ditto. - -2001-09-10 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::Populate): Now define operators too. - (TypeContainer.Operators): New property to access the list of operators - in a type. - (Operator.OperatorMethodBuilder): New member to hold the method builder - for the operator we are defining. - (Operator::Define): Implement. - -2001-09-10 Ravi Pratap <ravi@ximian.com> - - * class.cs (Event::Define): Make the prefixes of the accessor methods - addOn_ and removeOn_ - - * genericparser.cs (GenericParser::error): Overloaded method to handle the case - of the location being passed in too. Ideally, this should go later since all - error reporting should be done through the Report object. - - * class.cs (TypeContainer.Indexers): New property to access the list of indexers. - (Populate): Iterate thru the indexers we have and define them too. - (Indexer.GetMethodBuilder, .SetMethodBuilder): New members to hold the method builders - for the get and set accessors. - (Indexer::Define): Implement. - -2001-09-09 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (Binary::Resolve): Beginning of it. I scratched - my previous implementation, did not work. - - * typemanager.cs: Add a couple of missing types (the longs). - - * literal.cs: Use TypeManager.bool_type instead of getting it. - - * expression.cs (EventExpr): New kind of expressions. - (Expressio::ExprClassFromMemberInfo): finish - -2001-09-08 Miguel de Icaza <miguel@ximian.com> - - * assign.cs: Emit stores to static fields differently. - -2001-09-08 Ravi Pratap <ravi@ximian.com> - - * Merge in changes and adjust code to tackle conflicts. Backed out my - code in Assign::Resolve ;-) - -2001-09-08 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (CheckAttributeTarget): Modify call to error to use - instead Report.Error and also pass in the location. - (CSharpParser::Lexer): New readonly property to return the reference - to the Tokenizer object. - (declare_local_variables): Use Report.Error with location instead of plain - old error. - (CheckDef): Ditto. - - * class.cs (Operator::CheckUnaryOperator): Move into cs-parser.jay. - (Operator.CheckBinaryOperator): Ditto. - - * cs-parser.jay (operator_declarator): Update accordingly. - - * cs-parser.jay (CheckUnaryOperator): Modify to use Report.Error - (CheckBinaryOperator): Same here. - - * rootcontext.cs (LookupType): Add an extra lookup which simply does a lookup - on the name without any prefixes of namespace names etc. This is because we - already might have something already fully qualified like - 'System.Console.WriteLine' - - * assign.cs (Resolve): Begin implementation. Stuck ;-) - -2001-09-07 Ravi Pratap <ravi@ximian.com> - - * cs-tokenizer.cs (location): Return a string which also contains - the file name. - - * expression.cs (ElementAccess): New class for expressions of the - type 'element access.' - (BaseAccess): New class for expressions of the type 'base access.' - (CheckedExpr, UnCheckedExpr): New classes for Checked and Unchecked expressions - respectively. - - * cs-parser.jay (element_access): Implement action. - (base_access): Implement actions. - (checked_expression, unchecked_expression): Implement. - - * cs-parser.jay (local_variable_type): Correct and implement. - (type_suffixes, type_suffix_list, type_suffix): Implement actions. - - * cs-tokenizer.cs (real_type_suffix): Comment out the extra getchar. - - * cs-parser.jay (rank_specifiers): Remove space while concatenating the type's - name and the specifiers. - - * interface.cs (InterfaceAttr): New property to return the corresponding TypeAttributes - - * rootcontext.cs (CreateInterface): Use the InterfaceAttr property instead of - making them all public ;-) - - * cs-parser.jay (error): Remove entirely as we have an implementation in the base - class anyways. - -2001-09-07 Miguel de Icaza <miguel@ximian.com> - - * expression.cs (ExprClassFromMemberInfo): Return FieldExpr and - PropertyExprs. - (FieldExpr, PropertyExprs): New resolved expressions. - (SimpleName::MemberStaticCheck): Perform static checks for access - to non-static fields on static methods. Maybe this should be - generalized for MemberAccesses. - (SimpleName::ResolveSimpleName): More work on simple name - resolution. - - * cs-parser.jay (primary_expression/qualified_identifier): track - the parameter index. - - * codegen.cs (CodeGen::Save): Catch save exception, report error. - (EmitContext::EmitBoolExpression): Chain to expression generation - instead of temporary hack. - (::EmitStatementExpression): Put generic expression code generation. - - * assign.cs (Assign::Emit): Implement variable assignments to - local variables, parameters and fields. - -2001-09-06 Miguel de Icaza <miguel@ximian.com> - - * statement.cs (Block::GetVariableInfo): New method, returns the - VariableInfo for a variable name in a block. - (Block::GetVariableType): Implement in terms of GetVariableInfo - - * literal.cs (IntLiteral::Emit, FloatLiteral::Emit, - DoubleLiteral::Emit, CharLiteral::Emit, BoolLiteral::Emit): Implement - -2001-09-06 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (operator_declaration): Continue on my quest : update - to take attributes argument. - (event_declaration): Ditto. - (enum_declaration): Ditto. - (indexer_declaration): Ditto. - - * class.cs (Operator::Operator): Update constructor accordingly. - (Event::Event): Ditto. - - * delegate.cs (Delegate::Delegate): Same here. - - * enum.cs (Enum::Enum): Same here. - -2001-09-05 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (CheckAttributeTarget): Update to use the right error number. - - * ../tests/cs0658.cs : New file to demonstrate error 0658. - - * attribute.cs (Attributes): New class to encapsulate all attributes which were - being passed around as an arraylist. - (Attributes::AddAttribute): Method to add attribute sections. - - * cs-parser.jay (opt_attributes): Modify actions to use the new Attributes class. - (struct_declaration): Update accordingly. - (constant_declaration): Update. - (field_declaration): Update. - (method_header): Update. - (fixed_parameter): Update. - (parameter_array): Ditto. - (property_declaration): Ditto. - (destructor_declaration): Ditto. - - * class.cs (Struct::Struct): Update constructors accordingly. - (Class::Class): Ditto. - (Field::Field): Ditto. - (Method::Method): Ditto. - (Property::Property): Ditto. - (TypeContainer::OptAttribute): update property's return type. - - * interface.cs (Interface.opt_attributes): New member. - (Interface::Interface): Update to take the extra Attributes argument. - - * parameter.cs (Parameter::Parameter): Ditto. - - * constant.cs (Constant::Constant): Ditto. - - * interface.cs (InterfaceMemberBase): New OptAttributes field. - (InterfaceMemberBase::InterfaceMemberBase): Update constructor to take - the attributes as a parameter. - (InterfaceProperty): Update constructor call. - (InterfaceEvent): Ditto. - (InterfaceMethod): Ditto. - (InterfaceIndexer): Ditto. - - * cs-parser.jay (interface_indexer_declaration): Update call to constructor to - pass the attributes too. - (interface_event_declaration): Ditto. - (interface_property_declaration): Ditto. - (interface_method_declaration): Ditto. - (interface_declaration): Ditto. - -2001-09-05 Miguel de Icaza <miguel@ximian.com> - - * class.cs (Method::Define): Track the "static Main" definition to - create an entry point. - - * rootcontext.cs (RootContext::EntryPoint): MethodInfo that holds the - EntryPoint if we find it. - - * codegen.cs (EmitContext::EmitInvocation): Emit invocations. - (EmitContext::ig): Make this variable public. - - * driver.cs: Make the default output file be the first file name - with the .exe extension. - - Detect empty compilations - - Handle various kinds of output targets. Handle --target and - rename -t to --dumper. - - * expression.cs, literal.cs, assign.cs, constant.cs: All `Resolve' - methods inherited from Expression return now an Expression. This - will is used during the tree rewriting as we resolve them during - semantic analysis. - - (Expression::MemberLookup): Implements the MemberLookup (7.3) from - the spec. Missing entirely is the information about - accessability of elements of it. - - (Expression::ExprClassFromMemberInfo): New constructor for - Expressions that creates a fully initialized Expression based on - a MemberInfo that is one of Eventinfo, FieldINfo, PropertyInfo or - a Type. - - (Invocation::Resolve): Begin implementing resolution of invocations. - - * literal.cs (StringLiteral): Implement Emit. - -2001-09-05 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (error): Add new modifier because we are hiding an inherited - member. - -2001-09-04 Ravi Pratap <ravi@ximian.com> - - * cs-parser.jay (attribute_arguments): Implement actions. - (attribute): Fix bug in production. Implement action. - (attribute_list): Implement. - (attribute_target): Implement. - (attribute_target_specifier, opt_target_specifier): Implement - (CheckAttributeTarget): New method to check if the attribute target - is valid. - (attribute_section): Implement. - (opt_attributes): Implement. - - * attribute.cs : New file to handle attributes. - (Attribute): Class to hold attribute info. - - * cs-parser.jay (opt_attribute_target_specifier): Remove production - (attribute_section): Modify production to use 2 different rules to - achieve the same thing. 1 s/r conflict down ! - Clean out commented, useless, non-reducing dimension_separator rules. - - * class.cs (TypeContainer.attributes): New member to hold list - of attributes for a type. - (Struct::Struct): Modify to take one more argument, the attribute list. - (Class::Class): Ditto. - (Field::Field): Ditto. - (Method::Method): Ditto. - (Property::Property): Ditto. - - * cs-parser.jay (struct_declaration): Update constructor call to - pass in the attributes too. - (class_declaration): Ditto. - (constant_declaration): Ditto. - (field_declaration): Ditto. - (method_header): Ditto. - (fixed_parameter): Ditto. - (parameter_array): Ditto. - (property_declaration): Ditto. - - * constant.cs (Constant::Constant): Update constructor similarly. - Use System.Collections. - - * parameter.cs (Parameter::Parameter): Update as above. - -2001-09-02 Ravi Pratap <ravi@ximian.com> - - * class.cs (TypeContainer::AddDelegate): New method to add a delegate. - (TypeContainer.delegates): New member to hold list of delegates. - - * cs-parser.jay (delegate_declaration): Implement the action correctly - this time as I seem to be on crack ;-) - -2001-09-02 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs (RootContext::IsNamespace): new function, used to - tell whether an identifier represents a namespace. - - * expression.cs (NamespaceExpr): A namespace expression, used only - temporarly during expression resolution. - (Expression::ResolveSimpleName, ::ResolvePrimary, ::ResolveName): - utility functions to resolve names on expressions. - -2001-09-01 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs: Add hook for StatementExpressions. - - * class.cs: Fix inverted test for static flag in methods. - -2001-09-02 Ravi Pratap <ravi@ximian.com> - - * class.cs (Operator::CheckUnaryOperator): Correct error number used - to make it coincide with MS' number. - (Operator::CheckBinaryOperator): Ditto. - - * ../errors/errors.txt : Remove error numbers added earlier. - - * ../errors/cs1019.cs : Test case for error # 1019 - - * ../errros/cs1020.cs : Test case for error # 1020 - - * cs-parser.jay : Clean out commented cruft. - (dimension_separators, dimension_separator): Comment out. Ostensibly not - used anywhere - non-reducing rule. - (namespace_declarations): Non-reducing rule - comment out. - - * enum.cs (Enum::AddEnum): Rename to AddEnumMember as I was getting confused - with TypeContainer::AddEnum. - - * delegate.cs : New file for delegate handling classes. - (Delegate): Class for declaring delegates. - - * makefile : Update. - - * cs-parser.jay (delegate_declaration): Implement. - -2001-09-01 Ravi Pratap <ravi@che.iitm.ac.in> - - * class.cs (Event::Define): Implement. - (Event.EventBuilder): New member. - - * class.cs (TypeContainer::Populate): Update to define all enums and events - we have. - (Events): New property for the events arraylist we hold. Shouldn't we move to using - readonly fields for all these cases ? - -2001-08-31 Ravi Pratap <ravi@che.iitm.ac.in> - - * class.cs (Property): Revamp to use the convention of making fields readonly. - Accordingly modify code elsewhere. - - * class.cs : Apply patch from Mr. Mandar <go_mono@hotmail.com> for implementing - the Define method of the Property class. - - * class.cs : Clean up applied patch and update references to variables etc. Fix - trivial bug. - (TypeContainer::Populate): Update to define all the properties we have. Also - define all enumerations. - - * enum.cs (Define): Implement. - -2001-08-31 Ravi Pratap <ravi@che.iitm.ac.in> - - * cs-parser.jay (overloadable_operator): The semantic value is an - enum of the Operator class. - (operator_declarator): Implement actions. - (operator_declaration): Implement. - - * class.cs (Operator::CheckUnaryOperator): New static method to help in checking - validity of definitions. - (Operator::CheckBinaryOperator): Static method to check for binary operators - (TypeContainer::AddOperator): New method to add an operator to a type. - - * cs-parser.jay (indexer_declaration): Added line to actually call the - AddIndexer method so it gets added ;-) - - * ../errors/errors.txt : Update to include new error numbers. Are these numbers - already taken care of by the MS compiler ? - -2001-08-29 Ravi Pratap <ravi@che.iitm.ac.in> - - * class.cs (Operator): New class for operator declarations. - (Operator::OpType): Enum for the various operators. - -2001-08-29 Ravi Pratap <ravi@che.iitm.ac.in> - - * class.cs (TypeContainer::AddIndexer): Remove FIXME comment. We - ostensibly handle this in semantic analysis. - - * cs-parser.jay (general_catch_clause): Comment out - (specific_catch_clauses, specific_catch_clause): Ditto. - (opt_general_catch_clause, opt_specific_catch_clauses): Ditto - (catch_args, opt_catch_args): New productions. - (catch_clause): Rewrite to use the new productions above - (catch_clauses): Modify accordingly. - (opt_catch_clauses): New production to use in try_statement - (try_statement): Revamp. Basically, we get rid of one unnecessary rule - and re-write the code in the actions to extract the specific and - general catch clauses by being a little smart ;-) - - * ../tests/try.cs : Fix. It's not 'finalize' my friend, it's 'finally' ! - Hooray, try and catch statements parse fine ! - -2001-08-28 Ravi Pratap <ravi@che.iitm.ac.in> - - * statement.cs (Block::GetVariableType): Fix logic to extract the type - string from the hashtable of variables. - - * cs-parser.jay (event_accessor_declarations): Trivial fix. Man, how did - I end up making that mistake ;-) - (catch_clauses): Fixed gross error which made Key and Value of the - DictionaryEntry the same : $1 !! - -2001-08-28 Ravi Pratap <ravi@che.iitm.ac.in> - - * cs-tokenizer.cs (initTokens): Add keywords 'add' and 'remove' - - * cs-parser.jay (event_declaration): Correct to remove the semicolon - when the add and remove accessors are specified. - -2001-08-28 Ravi Pratap <ravi@che.iitm.ac.in> - - * cs-parser.jay (IndexerDeclaration): New helper class to hold - information about indexer_declarator. - (indexer_declarator): Implement actions. - (parsing_indexer): New local boolean used to keep track of whether - we are parsing indexers or properties. This is necessary because - implicit_parameters come into picture even for the get accessor in the - case of an indexer. - (get_accessor_declaration, set_accessor_declaration): Correspondingly modified. - - * class.cs (Indexer): New class for indexer declarations. - (TypeContainer::AddIndexer): New method to add an indexer to a type. - (TypeContainer::indexers): New member to hold list of indexers for the - type. - -2001-08-27 Ravi Pratap <ravi@che.iitm.ac.in> - - * cs-parser.jay (add_accessor_declaration): Implement action. - (remove_accessor_declaration): Implement action. - (event_accessors_declaration): Implement - (variable_declarators): swap statements for first rule - trivial. - - * class.cs (Event): New class to hold information about event - declarations. - (TypeContainer::AddEvent): New method to add an event to a type - (TypeContainer::events): New member to hold list of events. - - * cs-parser.jay (event_declaration): Implement actions. - -2001-08-27 Ravi Pratap <ravi@che.iitm.ac.in> - - * cs-parser.jay (dim_separators): Implement. Make it a string - concatenating all the commas together, just as they appear. - (opt_dim_separators): Modify accordingly - (rank_specifiers): Update accordingly. Basically do the same - thing - instead, collect the brackets here. - (opt_rank_sepcifiers): Modify accordingly. - (array_type): Modify to actually return the complete type string - instead of ignoring the rank_specifiers. - (expression_list): Implement to collect the expressions - (variable_initializer): Implement. We make it a list of expressions - essentially so that we can handle the array_initializer case neatly too. - (variable_initializer_list): Implement. - (array_initializer): Make it a list of variable_initializers - (opt_array_initializer): Modify accordingly. - - * expression.cs (New::NType): Add enumeration to help us - keep track of whether we have an object/delegate creation - or an array creation. - (New:NewType, New::Rank, New::Indices, New::Initializers): New - members to hold data about array creation. - (New:New): Modify to update NewType - (New:New): New Overloaded contructor for the array creation - case. - - * cs-parser.jay (array_creation_expression): Implement to call - the overloaded New constructor. - -2001-08-26 Ravi Pratap <ravi@che.iitm.ac.in> - - * class.cs (TypeContainer::Constructors): Return member - constructors instead of returning null. - -2001-08-26 Miguel de Icaza <miguel@ximian.com> - - * typemanager.cs (InitCoreTypes): Initialize the various core - types after we have populated the type manager with the user - defined types (this distinction will be important later while - compiling corlib.dll) - - * expression.cs, literal.cs, assign.cs, constant.cs: Started work - on Expression Classification. Now all expressions have a method - `Resolve' and a method `Emit'. - - * codegen.cs, cs-parser.jay: Fixed the bug that stopped code - generation from working. Also add some temporary debugging - code. - -2001-08-24 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs: Lots of code generation pieces. This is only the - beginning, will continue tomorrow with more touches of polish. We - handle the fundamentals of if, while, do, for, return. Others are - trickier and I need to start working on invocations soon. - - * gen-treedump.cs: Bug fix, use s.Increment here instead of - s.InitStatement. - - * codegen.cs (EmitContext): New struct, used during code - emission to keep a context. Most of the code generation will be - here. - - * cs-parser.jay: Add embedded blocks to the list of statements of - this block. So code generation proceeds in a top down fashion. - -2001-08-23 Miguel de Icaza <miguel@ximian.com> - - * statement.cs: Add support for multiple child blocks. - -2001-08-22 Miguel de Icaza <miguel@ximian.com> - - * codegen.cs (EmitCode): New function, will emit the code for a - Block of code given a TypeContainer and its ILGenerator. - - * statement.cs (Block): Standard public readonly optimization. - (Block::Block constructors): Link children. - (Block::Child): Child Linker. - (Block::EmitVariables): Emits IL variable declarations. - - * class.cs: Drop support for MethodGroups here, delay until - Semantic Analysis. - (Method::): Applied the same simplification that I did before, and - move from Properties to public readonly fields. - (Method::ParameterTypes): Returns the parameter types for the - function, and implements a cache that will be useful later when I - do error checking and the semantic analysis on the methods is - performed. - (Constructor::GetCallingConvention): Renamed from CallingConvetion - and made a method, optional argument tells whether this is a class - or a structure to apply the `has-this' bit. - (Method::GetCallingConvention): Implement, returns the calling - convention. - (Method::Define): Defines the type, a second pass is performed - later to populate the methods. - - (Constructor::ParameterTypes): implement a cache similar to the - one on Method::ParameterTypes, useful later when we do semantic - analysis. - - (TypeContainer::EmitMethod): New method. Emits methods. - - * expression.cs: Removed MethodGroup class from here. - - * parameter.cs (Parameters::GetCallingConvention): new method. - -2001-08-21 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer::Populate): Drop RootContext from the - argument. - - (Constructor::CallingConvention): Returns the calling convention. - (Constructor::ParameterTypes): Returns the constructor parameter - types. - - (TypeContainer::AddConstructor): Keep track of default constructor - and the default static constructor. - - (Constructor::) Another class that starts using `public readonly' - instead of properties. - - (Constructor::IsDefault): Whether this is a default constructor. - - (Field::) use readonly public fields instead of properties also. - - (TypeContainer::TypeAttr, TypeContainer::AddConstructor): Keep - track of static constructors; If none is used, turn on - BeforeFieldInit in the TypeAttributes. - - * cs-parser.jay (opt_argument_list): now the return can be null - for the cases where there are no arguments. - - (constructor_declarator): If there is no implicit `base' or - `this', then invoke the default parent constructor. - - * modifiers.cs (MethodAttr): New static function maps a set of - modifiers flags into a MethodAttributes enum - (FieldAttr): renamed from `Map'. So now we have FieldAttr, - MethodAttr, TypeAttr to represent the various mappings where the - modifiers are used. - (FieldAttr): Map also `readonly' to `FieldAttributes.InitOnly' - -2001-08-19 Miguel de Icaza <miguel@ximian.com> - - * parameter.cs (GetParameterInfo): Fix bug where there would be no - method arguments. - - * interface.cs (PopulateIndexer): Implemented the code generator - for interface indexers. - -2001-08-17 Miguel de Icaza <miguel@ximian.com> - - * interface.cs (InterfaceMemberBase): Now we track the new status - here. - - (PopulateProperty): Implement property population. Woohoo! Got - Methods and Properties going today. - - Removed all the properties for interfaces, and replaced them with - `public readonly' fields. - -2001-08-16 Miguel de Icaza <miguel@ximian.com> - - * interface.cs (AddEvent, AddMethod, AddIndexer, AddProperty): - initialize their hashtables/arraylists only when they are needed - instead of doing this always. - - * parameter.cs: Handle refs and out parameters. - - * cs-parser.jay: Use an ArrayList to construct the arguments - instead of the ParameterCollection, and then cast that to a - Parameter[] array. - - * parameter.cs: Drop the use of ParameterCollection and use - instead arrays of Parameters. - - (GetParameterInfo): Use the Type, not the Name when resolving - types. - -2001-08-13 Miguel de Icaza <miguel@ximian.com> - - * parameter.cs: Eliminate the properties Name, Type and ModFlags, - and instead use public readonly fields. - - * class.cs: Put back walking code for type containers. - -2001-08-11 Miguel de Icaza <miguel@ximian.com> - - * class.cs (MakeConstant): Code to define constants. - - * rootcontext.cs (LookupType): New function. Used to locate types - - -2001-08-08 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs: OH MY! My trick works! It is amazing how nice - this System.Reflection code is. Kudos to Microsoft - - * typemanager.cs: Implement a type cache and avoid loading all - types at boot time. Wrap in LookupType the internals. This made - the compiler so much faster. Wow. I rule! - - * driver.cs: Make sure we always load mscorlib first (for - debugging purposes, nothing really important). - - * Renamespaced things that were on `CSC' to `CIR'. Maybe I should - have moved to `CSC' rather than `CIR'. Oh man! The confussion! - - * rootcontext.cs: Lookup types on their namespace; Lookup types - on namespaces that have been imported using the `using' keyword. - - * class.cs (TypeContainer::TypeAttr): Virtualize. - (Class::TypeAttr): Return attributes suitable for this bad boy. - (Struct::TypeAttr): ditto. - Handle nested classes. - (TypeContainer::) Remove all the type visiting code, it is now - replaced with the rootcontext.cs code - - * rootcontext.cs (GetClassBases): Added support for structs. - -2001-08-06 Miguel de Icaza <miguel@ximian.com> - - * interface.cs, statement.cs, class.cs, parameter.cs, - rootcontext.cs, gen-treedump.cs, enum.cs, cs-parse.jay: - Drop use of TypeRefs, and use strings instead. - -2001-08-04 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs: - - * class.cs (Struct::Struct): set the SEALED flags after - checking the modifiers. - (TypeContainer::TypeAttr): new property, returns the - TypeAttributes for a class. - - * cs-parser.jay (type_list): Oops, list production was creating a - new list of base types. - - * rootcontext.cs (StdLib): New property. - (GetInterfaceTypeByName): returns an interface by type name, and - encapsulates error handling here. - (GetInterfaces): simplified. - (ResolveTree): Encapsulated all the tree resolution here. - (CreateClass, GetClassBases, GetInterfaceOrClass): Create class - types. - - * driver.cs: Add support for --nostdlib, to avoid loading the - default assemblies. - (Main): Do not put tree resolution here. - - * rootcontext.cs: Beginning of the class resolution. - -2001-08-03 Miguel de Icaza <miguel@ximian.com> - - * rootcontext.cs: Provide better error reporting. - - * cs-parser.jay (interface_base): set our $$ to be interfaces. - - * rootcontext.cs (CreateInterface): Handle the case where there - are no parent interfaces. - - (CloseTypes): Routine to flush types at the end. - (CreateInterface): Track types. - (GetInterfaces): Returns an array of Types from the list of - defined interfaces. - - * typemanager.c (AddUserType): Mechanism to track user types (puts - the type on the global type hash, and allows us to close it at the - end). - -2001-08-02 Miguel de Icaza <miguel@ximian.com> - - * tree.cs: Removed RecordType, added RecordClass, RecordStruct and - RecordInterface instead. - - * cs-parser.jay: Updated to reflect changes above. - - * decl.cs (Definition): Keep track of the TypeBuilder type that - represents this type here. Not sure we will use it in the long - run, but wont hurt for now. - - * driver.cs: Smaller changes to accomodate the new code. - - Call ResolveInterfaceBases, Call ResolveClassBases, Save assembly - when done. - - * rootcontext.cs (CreateInterface): New method, used to create - the System.TypeBuilder type for interfaces. - (ResolveInterfaces): new entry point to resolve the interface - hierarchy. - (CodeGen): Property, used to keep track of the code generator. - -2001-07-26 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Add a second production for delegate_declaration - with `VOID'. - - (enum_body): Put an opt_comma here instead of putting it on - enum_body or enum_member_declarations so we can handle trailing - commas on enumeration members. Gets rid of a shift/reduce. - - (type_list): Need a COMMA in the middle. - - (indexer_declaration): Tell tokenizer to recognize get/set - - * Remove old targets. - - * Re-add the parser target. - -2001-07-13 Simon Cozens <simon@simon-cozens.org> - - * cs-parser.jay: Add precendence rules for a number of operators - ot reduce the number of shift/reduce conflicts in the grammar. - -2001-07-17 Miguel de Icaza <miguel@ximian.com> - - * tree.cs: moved IGenerator interface and renamed it to ITreeDump - and put it here. - - Get rid of old crufty code. - - * rootcontext.cs: Use this to keep track of the parsed - representation and the defined types available to the program. - - * gen-treedump.cs: adjust for new convention. - - * type.cs: Split out the type manager, and the assembly builder - from here. - - * typemanager.cs: the type manager will live here now. - - * cil-codegen.cs: And the code generator here. - -2001-07-14 Sean MacIsaac <macisaac@ximian.com> - - * makefile: Fixed up for easy making. - -2001-07-13 Simon Cozens <simon@simon-cozens.org> - - * cs-parser.jay (rank_specifier): Remove a conflict by reordering - the - - (unary_expression): Expand pre_increment_expression and - post_decrement_expression to reduce a shift/reduce. - -2001-07-11 Simon Cozens - - * cs-tokenizer.cs: Hex numbers should begin with a 0. - - Improve allow_keyword_as_indent name. - -2001-06-19 Miguel de Icaza <miguel@ximian.com> - - * Adjustments for Beta2. - -2001-06-13 Miguel de Icaza <miguel@ximian.com> - - * decl.cs: Added `Define' abstract method. - (InTransit): new property, used to catch recursive definitions. - - * interface.cs: Implement `Define'. - - * modifiers.cs: Map Modifiers.constants to - System.Reflection.TypeAttribute flags. - - * class.cs: Keep track of types and user-defined types. - (BuilderInit): New method for creating an assembly - (ResolveType): New function to launch the resolution process, only - used by interfaces for now. - - * cs-parser.jay: Keep track of Classes, Structs and Interfaces - that are inserted into the name space. - -2001-06-08 Miguel de Icaza <miguel@ximian.com> - - * ARGH. I have screwed up my tree so many times due to the use of - rsync rather than using CVS. Going to fix this at once. - - * driver.cs: Objetify driver. Load assemblies, use assemblies to - load types. - -2001-06-07 Miguel de Icaza <miguel@ximian.com> - - * Experiment successful: Use System.Type rather that our own - version of Type. - -2001-05-25 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Removed nsAliases from here. - - Use new namespaces, handle `using XXX;' - - * namespace.cs: Reimplemented namespace handling, use a recursive - definition of the class. Now we can keep track of using clauses - and catch invalid using clauses. - -2001-05-24 Miguel de Icaza <miguel@ximian.com> - - * gen-treedump.cs: Adapted for all the renaming. - - * expression.cs (Expression): this class now has a Type property - which returns an expression Type. - - (Probe::, New::, TypeOf::, SizeOf::, Constant::): renamed from - `Type', as this has a different meaning now in the base - -2001-05-22 Miguel de Icaza <miguel@ximian.com> - - * interface.cs, class.cs: Removed from all the sources the - references to signature computation, as we can not do method - signature computation during the parsing time, as we are not - trying to solve at that point distinguishing: - - class X { - void a (Blah x) {} - void a (NS.Blah x) {} - } - - Which depending on the context might be valid or not, as we do not - know if Blah is the same thing as NS.Blah at that point. - - * Redid everything so the code uses TypeRefs now instead of - Types. TypeRefs are just temporary type placeholders, that need - to be resolved. They initially have a pointer to a string and the - current scope in which they are used. This is used later by the - compiler to resolve the reference to an actual Type. - - * DeclSpace is no longer a CIR.Type, and neither are - TypeContainers (Class and Struct) nor Interfaces nor Enums. They - are all DeclSpaces, but no Types. - - * type.cs (TypeRefManager): This implements the TypeRef manager, - which keeps track of all the types that need to be resolved after - the parsing has finished. - -2001-05-13 Miguel de Icaza <miguel@ximian.com> - - * ARGH. We are going to have to store `foreach' as a class rather - than resolving it, as we need to verify error 1579 after name - resolution. *OR* we could keep a flag that says `This request to - IEnumerator comes from a foreach statement' which we can then use - to generate the error. - -2001-05-10 Miguel de Icaza <miguel@ximian.com> - - * class.cs (TypeContainer.AddMethod): we now add methods to the - MethodGroup instead of the method hashtable. - - * expression.cs: Add MethodGroup abstraction, which gets us one - step closer to the specification in the way we handle method - declarations. - - * cs-parser.jay (primary_expression): qualified_identifier now - tried to match up an identifier to a local variable reference or - to a parameter reference. - - current_local_parameters is now a parser global variable that - points to the current parameters for the block, used during name - lookup. - - (property_declaration): Now creates an implicit `value' argument to - the set accessor. - -2001-05-09 Miguel de Icaza <miguel@ximian.com> - - * parameter.cs: Do not use `param' arguments as part of the - signature, per the spec. - -2001-05-08 Miguel de Icaza <miguel@ximian.com> - - * decl.cs: Base class for classes, structs and interfaces. This - is the "Declaration Space" - - * cs-parser.jay: Use CheckDef for checking declaration errors - instead of having one on each function. - - * class.cs: Factor out some code for handling error handling in - accordance to the "Declarations" section in the "Basic Concepts" - chapter in the ECMA C# spec. - - * interface.cs: Make all interface member classes derive from - InterfaceMemberBase. - -2001-05-07 Miguel de Icaza <miguel@ximian.com> - - * Many things: all interfaces are parsed and generated in - gen-treedump. Support for member variables, constructors, - destructors, properties, constants is there. - - Beginning of the IL backend, but very little done, just there for - testing purposes. - -2001-04-29 Miguel de Icaza <miguel@ximian.com> - - * cs-parser.jay: Fix labeled statement. - - * cs-tokenizer.cs (escape): Escape " and ' always. - ref_line, ref_name: keep track of the line/filename as instructed - by #line by the compiler. - Parse #line. - -2001-04-27 Miguel de Icaza <miguel@ximian.com> - - * System.CodeDOM/CodeBinaryOperatorExpression.cs: Rearrange enum - to match the values in System.CodeDOM. - - Divid renamed to Divide. - - * System.CodeDOM/CodeForLoopStatement.cs: Always have valid - statements. - (Statements.set): remove. - - * System.CodeDOM/CodeCatchClause.cs: always have a valid - statements. - - * System.CodeDOM/CodeIfStatement.cs: trueStatements and - falseStatements always have valid values. - - * cs-parser.jay: Use System.CodeDOM now. - diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs deleted file mode 100755 index 674ce15fd6a..00000000000 --- a/mcs/mcs/class.cs +++ /dev/null @@ -1,4737 +0,0 @@ -// -// class.cs: Class and Struct handlers -// -// Authors: Miguel de Icaza (miguel@gnu.org) -// Martin Baulig (martin@gnome.org) -// -// Licensed under the terms of the GNU GPL -// -// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com) -// -// -// 2002-10-11 Miguel de Icaza <miguel@ximian.com> -// -// * class.cs: Following the comment from 2002-09-26 to AddMethod, I -// have fixed a remaining problem: not every AddXXXX was adding a -// fully qualified name. -// -// Now everyone registers a fully qualified name in the DeclSpace as -// being defined instead of the partial name. -// -// Downsides: we are slower than we need to be due to the excess -// copies and the names being registered this way. -// -// The reason for this is that we currently depend (on the corlib -// bootstrap for instance) that types are fully qualified, because -// we dump all the types in the namespace, and we should really have -// types inserted into the proper namespace, so we can only store the -// basenames in the defined_names array. -// -// -#define CACHE -using System; -using System.Collections; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.CompilerServices; -using System.Diagnostics.SymbolStore; - -namespace Mono.CSharp { - - /// <summary> - /// This is the base class for structs and classes. - /// </summary> - public class TypeContainer : DeclSpace, IMemberContainer { - // Holds a list of classes and structures - ArrayList types; - - // Holds the list of properties - ArrayList properties; - - // Holds the list of enumerations - ArrayList enums; - - // Holds the list of delegates - ArrayList delegates; - - // Holds the list of constructors - ArrayList instance_constructors; - - // Holds the list of fields - ArrayList fields; - - // Holds a list of fields that have initializers - ArrayList initialized_fields; - - // Holds a list of static fields that have initializers - ArrayList initialized_static_fields; - - // Holds the list of constants - ArrayList constants; - - // Holds the list of - ArrayList interfaces; - - // Holds order in which interfaces must be closed - ArrayList interface_order; - - // Holds the methods. - ArrayList methods; - - // Holds the events - ArrayList events; - - // Holds the indexers - ArrayList indexers; - - // Holds the operators - ArrayList operators; - - // The emit context for toplevel objects. - EmitContext ec; - - // - // Pointers to the default constructor and the default static constructor - // - Constructor default_constructor; - Constructor default_static_constructor; - - // - // Whether we have seen a static constructor for this class or not - // - bool have_static_constructor = false; - - // - // Whether we have at least one non-static field - // - bool have_nonstatic_fields = false; - - // - // This one is computed after we can distinguish interfaces - // from classes from the arraylist `type_bases' - // - string base_class_name; - - ArrayList type_bases; - - // Attributes for this type - protected Attributes attributes; - - // Information in the case we are an attribute type - - public AttributeTargets Targets = AttributeTargets.All; - public bool AllowMultiple = false; - public bool Inherited; - - // The interfaces we implement. - Type [] ifaces; - - // The parent member container and our member cache - IMemberContainer parent_container; - MemberCache member_cache; - - // - // The indexer name for this class - // - public string IndexerName; - - public TypeContainer (TypeContainer parent, string name, Location l) - : base (parent, name, l) - { - string n; - types = new ArrayList (); - - if (parent == null) - n = ""; - else - n = parent.Name; - - base_class_name = null; - - //Console.WriteLine ("New class " + name + " inside " + n); - } - - public AdditionResult AddConstant (Const constant) - { - AdditionResult res; - string basename = constant.Name; - - if ((res = IsValid (basename)) != AdditionResult.Success) - return res; - - if (constants == null) - constants = new ArrayList (); - - constants.Add (constant); - DefineName (Name + "." + basename, constant); - - return AdditionResult.Success; - } - - public AdditionResult AddEnum (Mono.CSharp.Enum e) - { - AdditionResult res; - - if ((res = IsValid (e.Basename)) != AdditionResult.Success) - return res; - - if (enums == null) - enums = new ArrayList (); - - enums.Add (e); - DefineName (e.Name, e); - - return AdditionResult.Success; - } - - public AdditionResult AddClass (Class c) - { - AdditionResult res; - - if ((res = IsValid (c.Basename)) != AdditionResult.Success) - return res; - - DefineName (c.Name, c); - types.Add (c); - - return AdditionResult.Success; - } - - public AdditionResult AddStruct (Struct s) - { - AdditionResult res; - - if ((res = IsValid (s.Basename)) != AdditionResult.Success) - return res; - - DefineName (s.Name, s); - types.Add (s); - - return AdditionResult.Success; - } - - public AdditionResult AddDelegate (Delegate d) - { - AdditionResult res; - - if ((res = IsValid (d.Basename)) != AdditionResult.Success) - return res; - - if (delegates == null) - delegates = new ArrayList (); - - DefineName (d.Name, d); - delegates.Add (d); - - return AdditionResult.Success; - } - - public AdditionResult AddMethod (Method method) - { - string basename = method.Name; - string fullname = Name + "." + basename; - - Object value = defined_names [fullname]; - - if (value != null && (!(value is Method))) - return AdditionResult.NameExists; - - if (basename == Basename) - return AdditionResult.EnclosingClash; - - if (methods == null) - methods = new ArrayList (); - - if (method.Name.IndexOf (".") != -1) - methods.Insert (0, method); - else - methods.Add (method); - - if (value == null) - DefineName (fullname, method); - - return AdditionResult.Success; - } - - public AdditionResult AddConstructor (Constructor c) - { - if (c.Name != Basename) - return AdditionResult.NotAConstructor; - - bool is_static = (c.ModFlags & Modifiers.STATIC) != 0; - - if (is_static){ - have_static_constructor = true; - if (default_static_constructor != null){ - Console.WriteLine ("I have a static constructor already"); - Console.WriteLine (" " + default_static_constructor); - return AdditionResult.MethodExists; - } - - default_static_constructor = c; - } else { - if (c.IsDefault ()){ - if (default_constructor != null) - return AdditionResult.MethodExists; - default_constructor = c; - } - - if (instance_constructors == null) - instance_constructors = new ArrayList (); - - instance_constructors.Add (c); - } - - return AdditionResult.Success; - } - - public AdditionResult AddInterface (Interface iface) - { - AdditionResult res; - - if ((res = IsValid (iface.Basename)) != AdditionResult.Success) - return res; - - if (interfaces == null) - interfaces = new ArrayList (); - interfaces.Add (iface); - DefineName (iface.Name, iface); - - return AdditionResult.Success; - } - - public AdditionResult AddField (Field field) - { - AdditionResult res; - string basename = field.Name; - - if ((res = IsValid (basename)) != AdditionResult.Success) - return res; - - if (fields == null) - fields = new ArrayList (); - - fields.Add (field); - - if (field.HasInitializer){ - if ((field.ModFlags & Modifiers.STATIC) != 0){ - if (initialized_static_fields == null) - initialized_static_fields = new ArrayList (); - - initialized_static_fields.Add (field); - - // - // We have not seen a static constructor, - // but we will provide static initialization of fields - // - have_static_constructor = true; - } else { - if (initialized_fields == null) - initialized_fields = new ArrayList (); - - initialized_fields.Add (field); - } - } - - if ((field.ModFlags & Modifiers.STATIC) == 0) - have_nonstatic_fields = true; - - DefineName (Name + "." + basename, field); - return AdditionResult.Success; - } - - public AdditionResult AddProperty (Property prop) - { - AdditionResult res; - string basename = prop.Name; - - if ((res = IsValid (basename)) != AdditionResult.Success) - return res; - - if (properties == null) - properties = new ArrayList (); - - if (prop.Name.IndexOf (".") != -1) - properties.Insert (0, prop); - else - properties.Add (prop); - DefineName (Name + "." + basename, prop); - - return AdditionResult.Success; - } - - public AdditionResult AddEvent (Event e) - { - AdditionResult res; - string basename = e.Name; - - if ((res = IsValid (basename)) != AdditionResult.Success) - return res; - - if (events == null) - events = new ArrayList (); - - events.Add (e); - DefineName (Name + "." + basename, e); - - return AdditionResult.Success; - } - - public AdditionResult AddIndexer (Indexer i) - { - if (indexers == null) - indexers = new ArrayList (); - - if (i.InterfaceType != null) - indexers.Insert (0, i); - else - indexers.Add (i); - - return AdditionResult.Success; - } - - public AdditionResult AddOperator (Operator op) - { - if (operators == null) - operators = new ArrayList (); - - operators.Add (op); - - return AdditionResult.Success; - } - - public void RegisterOrder (Interface iface) - { - if (interface_order == null) - interface_order = new ArrayList (); - - interface_order.Add (iface); - } - - public ArrayList Types { - get { - return types; - } - } - - public ArrayList Methods { - get { - return methods; - } - } - - public ArrayList Constants { - get { - return constants; - } - } - - public ArrayList Interfaces { - get { - return interfaces; - } - } - - public string Base { - get { - return base_class_name; - } - } - - public ArrayList Bases { - get { - return type_bases; - } - - set { - type_bases = value; - } - } - - public ArrayList Fields { - get { - return fields; - } - - set { - fields = value; - } - } - - public ArrayList InstanceConstructors { - get { - return instance_constructors; - } - } - - public ArrayList Properties { - get { - return properties; - } - } - - public ArrayList Events { - get { - return events; - } - } - - public ArrayList Enums { - get { - return enums; - } - } - - public ArrayList Indexers { - get { - return indexers; - } - } - - public ArrayList Operators { - get { - return operators; - } - } - - public ArrayList Delegates { - get { - return delegates; - } - } - - public Attributes OptAttributes { - get { - return attributes; - } - } - - public bool HaveStaticConstructor { - get { - return have_static_constructor; - } - } - - public virtual TypeAttributes TypeAttr { - get { - return Modifiers.TypeAttr (ModFlags, this); - } - } - - // - // Emits the instance field initializers - // - public bool EmitFieldInitializers (EmitContext ec) - { - ArrayList fields; - ILGenerator ig = ec.ig; - Expression instance_expr; - - if (ec.IsStatic){ - fields = initialized_static_fields; - instance_expr = null; - } else { - fields = initialized_fields; - instance_expr = new This (Location.Null).Resolve (ec); - } - - if (fields == null) - return true; - - foreach (Field f in fields){ - Expression e = f.GetInitializerExpression (ec); - if (e == null) - return false; - - Location l = f.Location; - FieldExpr fe = new FieldExpr (f.FieldBuilder, l); - fe.InstanceExpression = instance_expr; - Expression a = new Assign (fe, e, l); - - a = a.Resolve (ec); - if (a == null) - return false; - - if (a is ExpressionStatement) - ((ExpressionStatement) a).EmitStatement (ec); - else { - throw new Exception ("Assign.Resolve returned a non ExpressionStatement"); - } - } - - return true; - } - - // - // Defines the default constructors - // - void DefineDefaultConstructor (bool is_static) - { - Constructor c; - int mods = 0; - - c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters, - new ConstructorBaseInitializer ( - null, Parameters.EmptyReadOnlyParameters, - Location.Null), - Location.Null); - - if (is_static) - mods = Modifiers.STATIC; - - c.ModFlags = mods; - - AddConstructor (c); - - c.Block = new Block (null); - - } - - public void ReportStructInitializedInstanceError () - { - string n = TypeBuilder.FullName; - - foreach (Field f in initialized_fields){ - Report.Error ( - 573, Location, - "`" + n + "." + f.Name + "': can not have " + - "instance field initializers in structs"); - } - } - - /// <remarks> - /// The pending methods that need to be implemented (interfaces or abstract methods) - /// </remarks> - public PendingImplementation Pending; - - /// <summary> - /// This function computes the Base class and also the - /// list of interfaces that the class or struct @c implements. - /// - /// The return value is an array (might be null) of - /// interfaces implemented (as Types). - /// - /// The @parent argument is set to the parent object or null - /// if this is `System.Object'. - /// </summary> - Type [] GetClassBases (bool is_class, out Type parent, out bool error) - { - ArrayList bases = Bases; - int count; - int start, j, i; - - error = false; - - if (is_class) - parent = null; - else - parent = TypeManager.value_type; - - if (bases == null){ - if (is_class){ - if (RootContext.StdLib) - parent = TypeManager.object_type; - else if (Name != "System.Object") - parent = TypeManager.object_type; - } else { - // - // If we are compiling our runtime, - // and we are defining ValueType, then our - // parent is `System.Object'. - // - if (!RootContext.StdLib && Name == "System.ValueType") - parent = TypeManager.object_type; - } - - return null; - } - - // - // Bases should be null if there are no bases at all - // - count = bases.Count; - - if (is_class){ - Expression name = (Expression) bases [0]; - name = ResolveTypeExpr (name, false, Location); - - if (name == null){ - error = true; - return null; - } - - Type first = name.Type; - - if (first.IsClass){ - parent = first; - start = 1; - } else { - parent = TypeManager.object_type; - start = 0; - } - - if (!AsAccessible (parent, ModFlags)) - Report.Error (60, Location, - "Inconsistent accessibility: base class `" + - TypeManager.CSharpName (parent) + "' is less " + - "accessible than class `" + - Name + "'"); - - } else { - start = 0; - } - - Type [] ifaces = new Type [count-start]; - - for (i = start, j = 0; i < count; i++, j++){ - Expression name = (Expression) bases [i]; - Expression resolved = ResolveTypeExpr (name, false, Location); - if (resolved == null) - return null; - - bases [i] = resolved; - Type t = resolved.Type; - - if (t == null){ - error = true; - return null; - } - - if (is_class == false && !t.IsInterface){ - Report.Error (527, "In Struct `" + Name + "', type `"+ - name +"' is not an interface"); - error = true; - return null; - } - - if (t.IsSealed) { - string detail = ""; - - if (t.IsValueType) - detail = " (a class can not inherit from a struct/enum)"; - - Report.Error (509, "class `"+ Name + - "': Cannot inherit from sealed class `"+ - bases [i]+"'"+detail); - error = true; - return null; - } - - if (t.IsClass) { - if (parent != null){ - Report.Error (527, "In Class `" + Name + "', type `"+ - name+"' is not an interface"); - error = true; - return null; - } - } - - for (int x = 0; x < j; x++) { - if (t == ifaces [x]) { - Report.Error (528, "`" + name + "' is already listed in interface list"); - error = true; - return null; - } - } - - ifaces [j] = t; - } - - return TypeManager.ExpandInterfaces (ifaces); - } - - // - // Defines the type in the appropriate ModuleBuilder or TypeBuilder. - // - public override TypeBuilder DefineType () - { - Type parent; - bool error; - bool is_class; - - if (TypeBuilder != null) - return TypeBuilder; - - if (InTransit) - return null; - - InTransit = true; - - if (this is Class) - is_class = true; - else - is_class = false; - - ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags); - - ifaces = GetClassBases (is_class, out parent, out error); - - if (error) - return null; - - if (is_class && parent != null){ - if (parent == TypeManager.enum_type || - (parent == TypeManager.value_type && RootContext.StdLib) || - parent == TypeManager.delegate_type || - parent == TypeManager.array_type){ - Report.Error ( - 644, Location, "`" + Name + "' cannot inherit from " + - "special class `" + TypeManager.CSharpName (parent) + "'"); - return null; - } - } - - if (!is_class && TypeManager.value_type == null) - throw new Exception (); - - TypeAttributes type_attributes = TypeAttr; - - // if (parent_builder is ModuleBuilder) { - if (IsTopLevel){ - ModuleBuilder builder = CodeGen.ModuleBuilder; - TypeBuilder = builder.DefineType ( - Name, type_attributes, parent, ifaces); - - } else { - TypeBuilder builder = Parent.TypeBuilder; - TypeBuilder = builder.DefineNestedType ( - Basename, type_attributes, parent, ifaces); - } - - // - // Structs with no fields need to have at least one byte. - // The right thing would be to set the PackingSize in a DefineType - // but there are no functions that allow interfaces *and* the size to - // be specified. - // - - if (!is_class && !have_nonstatic_fields){ - TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type, - FieldAttributes.Private); - } - - // add interfaces that were not added at type creation (weird API issue) - if (!is_class && !have_nonstatic_fields && (ifaces != null)) { - foreach (Type i in ifaces) - TypeBuilder.AddInterfaceImplementation (i); - } - - // - // Finish the setup for the EmitContext - // - ec.ContainerType = TypeBuilder; - - TypeManager.AddUserType (Name, TypeBuilder, this, ifaces); - - if ((parent != null) && - (parent == TypeManager.attribute_type || - parent.IsSubclassOf (TypeManager.attribute_type))) { - RootContext.RegisterAttribute (this); - TypeManager.RegisterAttrType (TypeBuilder, this); - } else - RootContext.RegisterOrder (this); - - if (Interfaces != null) { - foreach (Interface iface in Interfaces) - iface.DefineType (); - } - - if (Types != null) { - foreach (TypeContainer tc in Types) - tc.DefineType (); - } - - if (Delegates != null) { - foreach (Delegate d in Delegates) - d.DefineType (); - } - - if (Enums != null) { - foreach (Enum en in Enums) - en.DefineType (); - } - - InTransit = false; - return TypeBuilder; - } - - - /// <summary> - /// Defines the MemberCore objects that are in the `list' Arraylist - /// - /// The `defined_names' array contains a list of members defined in - /// a base class - /// </summary> - static ArrayList remove_list = new ArrayList (); - void DefineMembers (ArrayList list, MemberInfo [] defined_names) - { - int idx; - - remove_list.Clear (); - - foreach (MemberCore mc in list){ - if (!mc.Define (this)){ - remove_list.Add (mc); - continue; - } - - if (defined_names == null) - continue; - - idx = Array.BinarySearch (defined_names, mc.Name, mif_compare); - if (idx < 0){ - if (RootContext.WarningLevel >= 4){ - if ((mc.ModFlags & Modifiers.NEW) != 0) - Warning_KewywordNewNotRequired (mc.Location, mc); - } - continue; - } - - MemberInfo match = defined_names [idx]; - - if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0)) - continue; - - // - // If we are both methods, let the method resolution emit warnings - // - if (match is MethodBase && mc is MethodCore) - continue; - - if ((mc.ModFlags & Modifiers.NEW) == 0) - Warning_KeywordNewRequired (mc.Location, defined_names [idx]); - } - - foreach (object o in remove_list) - list.Remove (o); - - remove_list.Clear (); - } - - // - // Defines the indexers, and also verifies that the IndexerNameAttribute in the - // class is consisten. Either it is `Item' or it is the name defined by all the - // indexers with the `IndexerName' attribute. - // - // Turns out that the IndexerNameAttribute is applied to each indexer, - // but it is never emitted, instead a DefaultName attribute is attached - // to the class. - // - void DefineIndexers () - { - string class_indexer_name = null; - - foreach (Indexer i in Indexers){ - string name; - - i.Define (this); - - name = i.IndexerName; - - if (i.InterfaceType != null) - continue; - - if (class_indexer_name == null){ - class_indexer_name = name; - continue; - } - - if (name == class_indexer_name) - continue; - - Report.Error ( - 668, "Two indexers have different names, " + - " you should use the same name for all your indexers"); - } - if (class_indexer_name == null) - class_indexer_name = "Item"; - IndexerName = class_indexer_name; - } - - static void Error_KeywordNotAllowed (Location loc) - { - Report.Error (1530, loc, "Keyword new not allowed for namespace elements"); - } - - /// <summary> - /// Populates our TypeBuilder with fields and methods - /// </summary> - public override bool DefineMembers (TypeContainer parent) - { - MemberInfo [] defined_names = null; - - if (interface_order != null){ - foreach (Interface iface in interface_order) - if ((iface.ModFlags & Modifiers.NEW) == 0) - iface.DefineMembers (this); - else - Error_KeywordNotAllowed (iface.Location); - } - - if (RootContext.WarningLevel > 1){ - Type ptype; - - // - // This code throws an exception in the comparer - // I guess the string is not an object? - // - ptype = TypeBuilder.BaseType; - if (ptype != null){ - defined_names = (MemberInfo []) FindMembers ( - ptype, MemberTypes.All & ~MemberTypes.Constructor, - BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static, null, null); - - Array.Sort (defined_names, mif_compare); - } - } - - if (constants != null) - DefineMembers (constants, defined_names); - - if (fields != null) - DefineMembers (fields, defined_names); - - if (this is Class){ - if (instance_constructors == null){ - if (default_constructor == null) - DefineDefaultConstructor (false); - } - - if (initialized_static_fields != null && - default_static_constructor == null) - DefineDefaultConstructor (true); - } - - if (this is Struct){ - // - // Structs can not have initialized instance - // fields - // - if (initialized_static_fields != null && - default_static_constructor == null) - DefineDefaultConstructor (true); - - if (initialized_fields != null) - ReportStructInitializedInstanceError (); - } - - Pending = PendingImplementation.GetPendingImplementations (this); - - // - // Constructors are not in the defined_names array - // - if (instance_constructors != null) - DefineMembers (instance_constructors, null); - - if (default_static_constructor != null) - default_static_constructor.Define (this); - - if (methods != null) - DefineMembers (methods, defined_names); - - if (properties != null) - DefineMembers (properties, defined_names); - - if (events != null) - DefineMembers (events, defined_names); - - if (indexers != null) { - DefineIndexers (); - } else - IndexerName = "Item"; - - if (operators != null){ - DefineMembers (operators, null); - - CheckPairedOperators (); - } - - if (enums != null) - DefineMembers (enums, defined_names); - - if (delegates != null) - DefineMembers (delegates, defined_names); - -#if CACHE - if (TypeBuilder.BaseType != null) - parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType); - - member_cache = new MemberCache (this); -#endif - - return true; - } - - public override bool Define (TypeContainer parent) - { - if (interface_order != null){ - foreach (Interface iface in interface_order) - if ((iface.ModFlags & Modifiers.NEW) == 0) - iface.Define (this); - } - - return true; - } - - /// <summary> - /// This function is based by a delegate to the FindMembers routine - /// </summary> - static bool AlwaysAccept (MemberInfo m, object filterCriteria) - { - return true; - } - - /// <summary> - /// This filter is used by FindMembers, and we just keep - /// a global for the filter to `AlwaysAccept' - /// </summary> - static MemberFilter accepting_filter; - - - /// <summary> - /// A member comparission method based on name only - /// </summary> - static IComparer mif_compare; - - static TypeContainer () - { - accepting_filter = new MemberFilter (AlwaysAccept); - mif_compare = new MemberInfoCompare (); - } - - /// <summary> - /// This method returns the members of this type just like Type.FindMembers would - /// Only, we need to use this for types which are _being_ defined because MS' - /// implementation can't take care of that. - /// </summary> - // - // FIXME: return an empty static array instead of null, that cleans up - // some code and is consistent with some coding conventions I just found - // out existed ;-) - // - // - // Notice that in various cases we check if our field is non-null, - // something that would normally mean that there was a bug elsewhere. - // - // The problem happens while we are defining p-invoke methods, as those - // will trigger a FindMembers, but this happens before things are defined - // - // Since the whole process is a no-op, it is fine to check for null here. - // - public override MemberList FindMembers (MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) - { - ArrayList members = new ArrayList (); - - int modflags = 0; - if ((bf & BindingFlags.Public) != 0) - modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED | - Modifiers.INTERNAL; - if ((bf & BindingFlags.NonPublic) != 0) - modflags |= Modifiers.PRIVATE; - - int static_mask = 0, static_flags = 0; - switch (bf & (BindingFlags.Static | BindingFlags.Instance)) { - case BindingFlags.Static: - static_mask = static_flags = Modifiers.STATIC; - break; - - case BindingFlags.Instance: - static_mask = Modifiers.STATIC; - static_flags = 0; - break; - - default: - static_mask = static_flags = 0; - break; - } - - Timer.StartTimer (TimerType.TcFindMembers); - - if (filter == null) - filter = accepting_filter; - - if ((mt & MemberTypes.Field) != 0) { - if (fields != null) { - foreach (Field f in fields) { - if ((f.ModFlags & modflags) == 0) - continue; - if ((f.ModFlags & static_mask) != static_flags) - continue; - - FieldBuilder fb = f.FieldBuilder; - if (fb != null && filter (fb, criteria) == true) - members.Add (fb); - } - } - - if (constants != null) { - foreach (Const con in constants) { - if ((con.ModFlags & modflags) == 0) - continue; - if ((con.ModFlags & static_mask) != static_flags) - continue; - - FieldBuilder fb = con.FieldBuilder; - if (fb != null && filter (fb, criteria) == true) - members.Add (fb); - } - } - } - - if ((mt & MemberTypes.Method) != 0) { - if (methods != null) { - foreach (Method m in methods) { - if ((m.ModFlags & modflags) == 0) - continue; - if ((m.ModFlags & static_mask) != static_flags) - continue; - - MethodBuilder mb = m.MethodBuilder; - - if (mb != null && filter (mb, criteria) == true) - members.Add (mb); - } - } - - if (operators != null){ - foreach (Operator o in operators) { - if ((o.ModFlags & modflags) == 0) - continue; - if ((o.ModFlags & static_mask) != static_flags) - continue; - - MethodBuilder ob = o.OperatorMethodBuilder; - if (ob != null && filter (ob, criteria) == true) - members.Add (ob); - } - } - - if (properties != null){ - foreach (Property p in properties){ - if ((p.ModFlags & modflags) == 0) - continue; - if ((p.ModFlags & static_mask) != static_flags) - continue; - - MethodBuilder b; - - b = p.GetBuilder; - if (b != null && filter (b, criteria) == true) - members.Add (b); - - b = p.SetBuilder; - if (b != null && filter (b, criteria) == true) - members.Add (b); - } - } - - if (indexers != null){ - foreach (Indexer ix in indexers){ - if ((ix.ModFlags & modflags) == 0) - continue; - if ((ix.ModFlags & static_mask) != static_flags) - continue; - - MethodBuilder b; - - b = ix.GetBuilder; - if (b != null && filter (b, criteria) == true) - members.Add (b); - - b = ix.SetBuilder; - if (b != null && filter (b, criteria) == true) - members.Add (b); - } - } - } - - if ((mt & MemberTypes.Event) != 0) { - if (events != null) - foreach (Event e in events) { - if ((e.ModFlags & modflags) == 0) - continue; - if ((e.ModFlags & static_mask) != static_flags) - continue; - - MemberInfo eb = e.EventBuilder; - if (eb != null && filter (eb, criteria) == true) - members.Add (e.EventBuilder); - } - } - - if ((mt & MemberTypes.Property) != 0){ - if (properties != null) - foreach (Property p in properties) { - if ((p.ModFlags & modflags) == 0) - continue; - if ((p.ModFlags & static_mask) != static_flags) - continue; - - MemberInfo pb = p.PropertyBuilder; - if (pb != null && filter (pb, criteria) == true) { - members.Add (p.PropertyBuilder); - } - } - - if (indexers != null) - foreach (Indexer ix in indexers) { - if ((ix.ModFlags & modflags) == 0) - continue; - if ((ix.ModFlags & static_mask) != static_flags) - continue; - - MemberInfo ib = ix.PropertyBuilder; - if (ib != null && filter (ib, criteria) == true) { - members.Add (ix.PropertyBuilder); - } - } - } - - if ((mt & MemberTypes.NestedType) != 0) { - if (types != null){ - foreach (TypeContainer t in types) { - if ((t.ModFlags & modflags) == 0) - continue; - - TypeBuilder tb = t.TypeBuilder; - if (tb != null && (filter (tb, criteria) == true)) - members.Add (tb); - } - } - - if (enums != null){ - foreach (Enum en in enums){ - if ((en.ModFlags & modflags) == 0) - continue; - - TypeBuilder tb = en.TypeBuilder; - if (tb != null && (filter (tb, criteria) == true)) - members.Add (tb); - } - } - - if (delegates != null){ - foreach (Delegate d in delegates){ - if ((d.ModFlags & modflags) == 0) - continue; - - TypeBuilder tb = d.TypeBuilder; - if (tb != null && (filter (tb, criteria) == true)) - members.Add (tb); - } - } - - if (interfaces != null){ - foreach (Interface iface in interfaces){ - if ((iface.ModFlags & modflags) == 0) - continue; - - TypeBuilder tb = iface.TypeBuilder; - if (tb != null && (filter (tb, criteria) == true)) - members.Add (tb); - } - } - } - - if ((mt & MemberTypes.Constructor) != 0){ - if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){ - foreach (Constructor c in instance_constructors){ - ConstructorBuilder cb = c.ConstructorBuilder; - if (cb != null) - if (filter (cb, criteria) == true) - members.Add (cb); - } - } - - if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){ - ConstructorBuilder cb = - default_static_constructor.ConstructorBuilder; - - if (cb != null) - if (filter (cb, criteria) == true) - members.Add (cb); - } - } - - // - // Lookup members in parent if requested. - // - if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) { - MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria); - members.AddRange (list); - } - - Timer.StopTimer (TimerType.TcFindMembers); - - return new MemberList (members); - } - - public override MemberCache MemberCache { - get { - return member_cache; - } - } - - public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) - { - TypeContainer tc = TypeManager.LookupTypeContainer (t); - - if (tc != null) - return tc.FindMembers (mt, bf, filter, criteria); - else - return new MemberList (t.FindMembers (mt, bf, filter, criteria)); - } - - // - // FindMethods will look for methods not only in the type `t', but in - // any interfaces implemented by the type. - // - public static MethodInfo [] FindMethods (Type t, BindingFlags bf, - MemberFilter filter, object criteria) - { - return null; - } - - /// <summary> - /// Emits the values for the constants - /// </summary> - public void EmitConstants () - { - if (constants != null) - foreach (Const con in constants) - con.EmitConstant (this); - return; - } - - /// <summary> - /// Emits the code, this step is performed after all - /// the types, enumerations, constructors - /// </summary> - public void Emit () - { - if (instance_constructors != null) - foreach (Constructor c in instance_constructors) - c.Emit (this); - - if (default_static_constructor != null) - default_static_constructor.Emit (this); - - if (methods != null) - foreach (Method m in methods) - m.Emit (this); - - if (operators != null) - foreach (Operator o in operators) - o.Emit (this); - - if (properties != null) - foreach (Property p in properties) - p.Emit (this); - - if (indexers != null){ - foreach (Indexer ix in indexers) - ix.Emit (this); - - CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr ( - this, IndexerName, ModFlags, Location); - TypeBuilder.SetCustomAttribute (cb); - } - - if (fields != null) - foreach (Field f in fields) - f.Emit (this); - - if (events != null){ - foreach (Event e in Events) - e.Emit (this); - } - - if (Pending != null) - if (Pending.VerifyPendingMethods ()) - return; - - Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location); - - // - // Check for internal or private fields that were never assigned - // - if (RootContext.WarningLevel >= 3) { - if (fields != null){ - foreach (Field f in fields) { - if ((f.ModFlags & Modifiers.PUBLIC) != 0) - continue; - - if (f.status == 0){ - Report.Warning ( - 169, f.Location, "Private field " + - MakeName (f.Name) + " is never used"); - continue; - } - - // - // Only report 649 on level 4 - // - if (RootContext.WarningLevel < 4) - continue; - - if ((f.status & Field.Status.ASSIGNED) != 0) - continue; - - Report.Warning ( - 649, f.Location, - "Field " + MakeName (f.Name) + " is never assigned " + - " to and will always have its default value"); - } - } - - if (events != null){ - foreach (Event e in events){ - if (e.status == 0) - Report.Warning (67, "The event " + MakeName (e.Name) + " is never used"); - } - } - } - -// if (types != null) -// foreach (TypeContainer tc in types) -// tc.Emit (); - } - - public override void CloseType () - { - try { - if (!Created){ - Created = true; - TypeBuilder.CreateType (); - } - } catch (TypeLoadException){ - // - // This is fine, the code still created the type - // -// Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name); -// Console.WriteLine (e.Message); - } catch { - Console.WriteLine ("In type: " + Name); - throw; - } - - if (Enums != null) - foreach (Enum en in Enums) - en.CloseType (); - - if (interface_order != null){ - foreach (Interface iface in interface_order) - iface.CloseType (); - } - - if (Types != null){ - foreach (TypeContainer tc in Types) - if (tc is Struct) - tc.CloseType (); - - foreach (TypeContainer tc in Types) - if (!(tc is Struct)) - tc.CloseType (); - } - - if (Delegates != null) - foreach (Delegate d in Delegates) - d.CloseType (); - } - - public string MakeName (string n) - { - return "`" + Name + "." + n + "'"; - } - - public void Warning_KeywordNewRequired (Location l, MemberInfo mi) - { - Report.Warning ( - 108, l, "The keyword new is required on " + - MakeName (mi.Name) + " because it hides `" + - mi.ReflectedType.Name + "." + mi.Name + "'"); - } - - public void Warning_KewywordNewNotRequired (Location l, MemberCore mc) - { - Report.Warning ( - 109, l, "The member " + MakeName (mc.Name) + " does not hide an " + - "inherited member, the keyword new is not required"); - } - - public static int CheckMember (string name, MemberInfo mi, int ModFlags) - { - return 0; - } - - // - // Performs the validation on a Method's modifiers (properties have - // the same properties). - // - public bool MethodModifiersValid (int flags, string n, Location loc) - { - const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE); - const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT); - const int nv = (Modifiers.NEW | Modifiers.VIRTUAL); - bool ok = true; - string name = MakeName (n); - - // - // At most one of static, virtual or override - // - if ((flags & Modifiers.STATIC) != 0){ - if ((flags & vao) != 0){ - Report.Error ( - 112, loc, "static method " + name + "can not be marked " + - "as virtual, abstract or override"); - ok = false; - } - } - - if (this is Struct){ - if ((flags & va) != 0){ - Modifiers.Error_InvalidModifier (loc, "virtual or abstract"); - ok = false; - } - } - - if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){ - Report.Error ( - 113, loc, name + - " marked as override cannot be marked as new or virtual"); - ok = false; - } - - // - // If the declaration includes the abstract modifier, then the - // declaration does not include static, virtual or extern - // - if ((flags & Modifiers.ABSTRACT) != 0){ - if ((flags & Modifiers.EXTERN) != 0){ - Report.Error ( - 180, loc, name + " can not be both abstract and extern"); - ok = false; - } - - if ((flags & Modifiers.VIRTUAL) != 0){ - Report.Error ( - 503, loc, name + " can not be both abstract and virtual"); - ok = false; - } - - if ((ModFlags & Modifiers.ABSTRACT) == 0){ - Report.Error ( - 513, loc, name + - " is abstract but its container class is not"); - ok = false; - - } - } - - if ((flags & Modifiers.PRIVATE) != 0){ - if ((flags & vao) != 0){ - Report.Error ( - 621, loc, name + - " virtual or abstract members can not be private"); - ok = false; - } - } - - if ((flags & Modifiers.SEALED) != 0){ - if ((flags & Modifiers.OVERRIDE) == 0){ - Report.Error ( - 238, loc, name + - " cannot be sealed because it is not an override"); - ok = false; - } - } - - return ok; - } - - // Access level of a type. - enum AccessLevel { - Public = 0, - ProtectedInternal = 1, - Internal = 2, - Protected = 3, - Private = 4 - } - - // Check whether `flags' denotes a more restricted access than `level' - // and return the new level. - static AccessLevel CheckAccessLevel (AccessLevel level, int flags) - { - AccessLevel old_level = level; - - if ((flags & Modifiers.INTERNAL) != 0) { - if ((flags & Modifiers.PROTECTED) != 0) { - if ((int) level < (int) AccessLevel.ProtectedInternal) - level = AccessLevel.ProtectedInternal; - } else { - if ((int) level < (int) AccessLevel.Internal) - level = AccessLevel.Internal; - } - } else if ((flags & Modifiers.PROTECTED) != 0) { - if ((int) level < (int) AccessLevel.Protected) - level = AccessLevel.Protected; - } else if ((flags & Modifiers.PRIVATE) != 0) - level = AccessLevel.Private; - - return level; - } - - // Return the access level for a new member which is defined in the current - // TypeContainer with access modifiers `flags'. - AccessLevel GetAccessLevel (int flags) - { - if ((flags & Modifiers.PRIVATE) != 0) - return AccessLevel.Private; - - AccessLevel level; - if (!IsTopLevel && (Parent != null)) - level = Parent.GetAccessLevel (flags); - else - level = AccessLevel.Public; - - return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags); - } - - // Return the access level for type `t', but don't give more access than `flags'. - static AccessLevel GetAccessLevel (Type t, int flags) - { - if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate) - return AccessLevel.Private; - - AccessLevel level; - if (TypeManager.IsBuiltinType (t)) - return AccessLevel.Public; - else if ((t.DeclaringType != null) && (t != t.DeclaringType)) - level = GetAccessLevel (t.DeclaringType, flags); - else { - level = CheckAccessLevel (AccessLevel.Public, flags); - } - - if (t.IsNestedPublic) - return level; - - if (t.IsNestedAssembly || t.IsNotPublic) { - if ((int) level < (int) AccessLevel.Internal) - level = AccessLevel.Internal; - } - - if (t.IsNestedFamily) { - if ((int) level < (int) AccessLevel.Protected) - level = AccessLevel.Protected; - } - - if (t.IsNestedFamORAssem) { - if ((int) level < (int) AccessLevel.ProtectedInternal) - level = AccessLevel.ProtectedInternal; - } - - return level; - } - - // - // Returns true if `parent' is as accessible as the flags `flags' - // given for this member. - // - public bool AsAccessible (Type parent, int flags) - { - while (parent.IsArray || parent.IsPointer || parent.IsByRef) - parent = parent.GetElementType (); - - AccessLevel level = GetAccessLevel (flags); - AccessLevel level2 = GetAccessLevel (parent, flags); - - return (int) level >= (int) level2; - } - - Hashtable builder_and_args; - - public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args) - { - if (builder_and_args == null) - builder_and_args = new Hashtable (); - return true; - } - - /// <summary> - /// Performs checks for an explicit interface implementation. First it - /// checks whether the `interface_type' is a base inteface implementation. - /// Then it checks whether `name' exists in the interface type. - /// </summary> - public bool VerifyImplements (Type interface_type, string full, string name, Location loc) - { - bool found = false; - - if (ifaces != null){ - foreach (Type t in ifaces){ - if (t == interface_type){ - found = true; - break; - } - } - } - - if (!found){ - Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'"); - return false; - } - - 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 - // - - string IMemberContainer.Name { - get { - return Name; - } - } - - Type IMemberContainer.Type { - get { - return TypeBuilder; - } - } - - IMemberContainer IMemberContainer.Parent { - get { - return parent_container; - } - } - - MemberCache IMemberContainer.MemberCache { - get { - return member_cache; - } - } - - bool IMemberContainer.IsInterface { - get { - return false; - } - } - - MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf) - { - return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null); - } - - // - // Operator pair checking - // - - class OperatorEntry { - public int flags; - public Type ret_type; - public Type type1, type2; - public Operator op; - public Operator.OpType ot; - - public OperatorEntry (int f, Operator o) - { - flags = f; - - ret_type = o.OperatorMethod.GetReturnType (); - Type [] pt = o.OperatorMethod.ParameterTypes; - type1 = pt [0]; - type2 = pt [1]; - op = o; - ot = o.OperatorType; - } - - public override int GetHashCode () - { - return ret_type.GetHashCode (); - } - - public override bool Equals (object o) - { - OperatorEntry other = (OperatorEntry) o; - - if (other.ret_type != ret_type) - return false; - if (other.type1 != type1) - return false; - if (other.type2 != type2) - return false; - return true; - } - } - - // - // Checks that some operators come in pairs: - // == and != - // > and < - // >= and <= - // - // They are matched based on the return type and the argument types - // - void CheckPairedOperators () - { - Hashtable pairs = new Hashtable (null, null); - - // Register all the operators we care about. - foreach (Operator op in operators){ - int reg = 0; - - switch (op.OperatorType){ - case Operator.OpType.Equality: - reg = 1; break; - case Operator.OpType.Inequality: - reg = 2; break; - - case Operator.OpType.GreaterThan: - reg = 1; break; - case Operator.OpType.LessThan: - reg = 2; break; - - case Operator.OpType.GreaterThanOrEqual: - reg = 1; break; - case Operator.OpType.LessThanOrEqual: - reg = 2; break; - } - if (reg == 0) - continue; - - OperatorEntry oe = new OperatorEntry (reg, op); - - object o = pairs [oe]; - if (o == null) - pairs [oe] = oe; - else { - oe = (OperatorEntry) o; - oe.flags |= reg; - } - } - - // - // Look for the mistakes. - // - foreach (DictionaryEntry de in pairs){ - OperatorEntry oe = (OperatorEntry) de.Key; - - if (oe.flags == 3) - continue; - - string s = ""; - switch (oe.ot){ - case Operator.OpType.Equality: - s = "!="; - break; - case Operator.OpType.Inequality: - s = "=="; - break; - case Operator.OpType.GreaterThan: - s = "<"; - break; - case Operator.OpType.LessThan: - s = ">"; - break; - case Operator.OpType.GreaterThanOrEqual: - s = "<="; - break; - case Operator.OpType.LessThanOrEqual: - s = ">="; - break; - } - Report.Error (216, oe.op.Location, - "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined"); - } - } - - - } - - public class Class : TypeContainer { - // <summary> - // Modifiers allowed in a class declaration - // </summary> - public const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.ABSTRACT | - Modifiers.SEALED | - Modifiers.UNSAFE; - - public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l) - : base (parent, name, l) - { - int accmods; - - if (parent.Parent == null) - accmods = Modifiers.INTERNAL; - else - accmods = Modifiers.PRIVATE; - - this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l); - this.attributes = attrs; - } - - // - // FIXME: How do we deal with the user specifying a different - // layout? - // - public override TypeAttributes TypeAttr { - get { - return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class; - } - } - } - - public class Struct : TypeContainer { - // <summary> - // Modifiers allowed in a struct declaration - // </summary> - public const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.UNSAFE | - Modifiers.PRIVATE; - - public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l) - : base (parent, name, l) - { - int accmods; - - if (parent.Parent == null) - accmods = Modifiers.INTERNAL; - else - accmods = Modifiers.PRIVATE; - - this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l); - - this.ModFlags |= Modifiers.SEALED; - this.attributes = attrs; - - } - - // - // FIXME: Allow the user to specify a different set of attributes - // in some cases (Sealed for example is mandatory for a class, - // but what SequentialLayout can be changed - // - public override TypeAttributes TypeAttr { - get { - return base.TypeAttr | - TypeAttributes.SequentialLayout | - TypeAttributes.Sealed | - TypeAttributes.BeforeFieldInit; - } - } - } - - public abstract class MethodCore : MemberBase { - public readonly Parameters Parameters; - protected Block block; - - // - // Parameters, cached for semantic analysis. - // - protected InternalParameters parameter_info; - protected Type [] parameter_types; - - public MethodCore (Expression type, int mod, int allowed_mod, string name, - Attributes attrs, Parameters parameters, Location loc) - : base (type, mod, allowed_mod, name, attrs, loc) - { - Parameters = parameters; - } - - // - // Returns the System.Type array for the parameters of this method - // - public Type [] ParameterTypes { - get { - return parameter_types; - } - } - - public InternalParameters ParameterInfo - { - get { - return parameter_info; - } - } - - public Block Block { - get { - return block; - } - - set { - block = value; - } - } - - protected virtual bool DoDefineParameters (TypeContainer parent) - { - // Check if arguments were correct - parameter_types = Parameters.GetParameterInfo (parent); - if ((parameter_types == null) || !CheckParameters (parent, parameter_types)) - return false; - - parameter_info = new InternalParameters (parent, Parameters); - - return true; - } - - public CallingConventions GetCallingConvention (bool is_class) - { - CallingConventions cc = 0; - - cc = Parameters.GetCallingConvention (); - - if (is_class) - if ((ModFlags & Modifiers.STATIC) == 0) - cc |= CallingConventions.HasThis; - - // FIXME: How is `ExplicitThis' used in C#? - - return cc; - } - - public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder) - { - // - // Define each type attribute (in/out/ref) and - // the argument names. - // - Parameter [] p = Parameters.FixedParameters; - int i = 0; - - MethodBuilder mb = null; - ConstructorBuilder cb = null; - - if (builder is MethodBuilder) - mb = (MethodBuilder) builder; - else - cb = (ConstructorBuilder) builder; - - if (p != null){ - for (i = 0; i < p.Length; i++) { - ParameterBuilder pb; - - if (mb == null) - pb = cb.DefineParameter ( - i + 1, p [i].Attributes, p [i].Name); - else - pb = mb.DefineParameter ( - i + 1, p [i].Attributes, p [i].Name); - - Attributes attr = p [i].OptAttributes; - if (attr != null) - Attribute.ApplyAttributes (ec, pb, pb, attr, Location); - } - } - - if (Parameters.ArrayParameter != null){ - ParameterBuilder pb; - Parameter array_param = Parameters.ArrayParameter; - - if (mb == null) - pb = cb.DefineParameter ( - i + 1, array_param.Attributes, - array_param.Name); - else - pb = mb.DefineParameter ( - i + 1, array_param.Attributes, - array_param.Name); - - CustomAttributeBuilder a = new CustomAttributeBuilder ( - TypeManager.cons_param_array_attribute, new object [0]); - - pb.SetCustomAttribute (a); - } - } - } - - public class Method : MethodCore { - public MethodBuilder MethodBuilder; - public MethodData MethodData; - - /// <summary> - /// Modifiers allowed in a class declaration - /// </summary> - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.VIRTUAL | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.ABSTRACT | - Modifiers.UNSAFE | - Modifiers.EXTERN; - - // - // return_type can be "null" for VOID values. - // - public Method (Expression return_type, int mod, string name, Parameters parameters, - Attributes attrs, Location l) - : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l) - { } - - // - // Returns the `System.Type' for the ReturnType of this - // function. Provides a nice cache. (used between semantic analysis - // and actual code generation - // - public Type GetReturnType () - { - return MemberType; - } - - // Whether this is an operator method. - public bool IsOperator; - - void DuplicateEntryPoint (MethodInfo b, Location location) - { - Report.Error ( - 17, location, - "Program `" + CodeGen.FileName + - "' has more than one entry point defined: `" + - TypeManager.CSharpSignature(b) + "'"); - } - - void Report28 (MethodInfo b) - { - if (RootContext.WarningLevel < 4) - return; - - Report.Warning ( - 28, Location, - "`" + TypeManager.CSharpSignature(b) + - "' has the wrong signature to be an entry point"); - } - - public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo) - { - if (b.ReturnType != TypeManager.void_type && - b.ReturnType != TypeManager.int32_type) - return false; - - if (pinfo.Count == 0) - return true; - - if (pinfo.Count > 1) - return false; - - Type t = pinfo.ParameterType(0); - if (t.IsArray && - (t.GetArrayRank() == 1) && - (t.GetElementType() == TypeManager.string_type) && - (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE)) - return true; - else - return false; - } - - // - // Checks our base implementation if any - // - protected override bool CheckBase (TypeContainer parent) - { - // Check whether arguments were correct. - if (!DoDefineParameters (parent)) - return false; - - MethodSignature ms = new MethodSignature (Name, null, ParameterTypes); - if (!IsOperator) { - MemberList mi_this; - - mi_this = TypeContainer.FindMembers ( - parent.TypeBuilder, MemberTypes.Method, - BindingFlags.NonPublic | BindingFlags.Public | - BindingFlags.Static | BindingFlags.Instance | - BindingFlags.DeclaredOnly, - MethodSignature.method_signature_filter, ms); - - if (mi_this.Count > 0) { - Report.Error (111, Location, "Class `" + parent.Name + "' " + - "already defines a member called `" + Name + "' " + - "with the same parameter types"); - return false; - } - } - - // - // Verify if the parent has a type with the same name, and then - // check whether we have to create a new slot for it or not. - // - Type ptype = parent.TypeBuilder.BaseType; - - // ptype is only null for System.Object while compiling corlib. - if (ptype != null){ - MemberList mi, mi_static, mi_instance; - - mi_static = TypeContainer.FindMembers ( - ptype, MemberTypes.Method, - BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, - MethodSignature.inheritable_method_signature_filter, ms); - - mi_instance = TypeContainer.FindMembers ( - ptype, MemberTypes.Method, - BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, - MethodSignature.inheritable_method_signature_filter, - ms); - - if (mi_instance.Count > 0){ - mi = mi_instance; - } else if (mi_static.Count > 0) - mi = mi_static; - else - mi = null; - - if (mi != null && mi.Count > 0){ - parent_method = (MethodInfo) mi [0]; - string name = parent_method.DeclaringType.Name + "." + - parent_method.Name; - - if (!CheckMethodAgainstBase (parent, flags, parent_method, name)) - return false; - - if ((ModFlags & Modifiers.NEW) == 0) { - Type parent_ret = TypeManager.TypeToCoreType ( - parent_method.ReturnType); - - if (parent_ret != MemberType) { - Report.Error ( - 508, parent.MakeName (Name) + ": cannot " + - "change return type when overriding " + - "inherited member " + name); - return false; - } - } - } else { - if ((ModFlags & Modifiers.NEW) != 0) - WarningNotHiding (parent); - - if ((ModFlags & Modifiers.OVERRIDE) != 0){ - Report.Error (115, Location, - parent.MakeName (Name) + - " no suitable methods found to override"); - } - } - } else if ((ModFlags & Modifiers.NEW) != 0) - WarningNotHiding (parent); - - return true; - } - - // - // Creates the type - // - public override bool Define (TypeContainer parent) - { - if (!DoDefine (parent)) - return false; - - if (!CheckBase (parent)) - return false; - - CallingConventions cc = GetCallingConvention (parent is Class); - - MethodData = new MethodData (this, null, MemberType, ParameterTypes, - ParameterInfo, cc, OptAttributes, - ModFlags, flags, true); - - if (!MethodData.Define (parent)) - return false; - - MethodBuilder = MethodData.MethodBuilder; - - // - // This is used to track the Entry Point, - // - if (Name == "Main" && - ((ModFlags & Modifiers.STATIC) != 0) && - (RootContext.MainClass == null || - RootContext.MainClass == parent.TypeBuilder.FullName)){ - if (IsEntryPoint (MethodBuilder, ParameterInfo)) { - if (RootContext.EntryPoint == null) { - RootContext.EntryPoint = MethodBuilder; - RootContext.EntryPointLocation = Location; - } else { - DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation); - DuplicateEntryPoint (MethodBuilder, Location); - } - } else - Report28(MethodBuilder); - } - - return true; - } - - // - // Emits the code - // - public void Emit (TypeContainer parent) - { - MethodData.Emit (parent, Block, this); - } - } - - public abstract class ConstructorInitializer { - ArrayList argument_list; - ConstructorInfo parent_constructor; - Parameters parameters; - Location loc; - - public ConstructorInitializer (ArrayList argument_list, Parameters parameters, - Location loc) - { - this.argument_list = argument_list; - this.parameters = parameters; - this.loc = loc; - } - - public ArrayList Arguments { - get { - return argument_list; - } - } - - public bool Resolve (EmitContext ec) - { - Expression parent_constructor_group; - Type t; - - ec.CurrentBlock = new Block (null, true, parameters); - - if (argument_list != null){ - foreach (Argument a in argument_list){ - if (!a.Resolve (ec, loc)) - return false; - } - } - - ec.CurrentBlock = null; - - if (this is ConstructorBaseInitializer) { - if (ec.ContainerType.BaseType == null) - return true; - - t = ec.ContainerType.BaseType; - if (ec.ContainerType.IsValueType) { - Report.Error (522, loc, - "structs cannot call base class constructors"); - return false; - } - } else - t = ec.ContainerType; - - parent_constructor_group = Expression.MemberLookup ( - ec, t, null, t, ".ctor", - MemberTypes.Constructor, - BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, - loc); - - if (parent_constructor_group == null){ - Report.Error (1501, loc, - "Can not find a constructor for this argument list"); - return false; - } - - parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, - (MethodGroupExpr) parent_constructor_group, argument_list, loc); - - if (parent_constructor == null){ - Report.Error (1501, loc, - "Can not find a constructor for this argument list"); - return false; - } - - return true; - } - - public void Emit (EmitContext ec) - { - if (parent_constructor != null){ - if (ec.IsStatic) - Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc); - else - Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc); - } - } - } - - public class ConstructorBaseInitializer : ConstructorInitializer { - public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) : - base (argument_list, pars, l) - { - } - } - - public class ConstructorThisInitializer : ConstructorInitializer { - public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) : - base (argument_list, pars, l) - { - } - } - - public class Constructor : MethodCore { - public ConstructorBuilder ConstructorBuilder; - public ConstructorInitializer Initializer; - new public Attributes OptAttributes; - - // <summary> - // Modifiers allowed for a constructor. - // </summary> - public const int AllowedModifiers = - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.STATIC | - Modifiers.UNSAFE | - Modifiers.EXTERN | - Modifiers.PRIVATE; - - // - // The spec claims that static is not permitted, but - // my very own code has static constructors. - // - public Constructor (string name, Parameters args, ConstructorInitializer init, Location l) - : base (null, 0, AllowedModifiers, name, null, args, l) - { - Initializer = init; - } - - // - // Returns true if this is a default constructor - // - public bool IsDefault () - { - if ((ModFlags & Modifiers.STATIC) != 0) - return (Parameters.FixedParameters == null ? true : Parameters.Empty) && - (Parameters.ArrayParameter == null ? true : Parameters.Empty); - - else - return (Parameters.FixedParameters == null ? true : Parameters.Empty) && - (Parameters.ArrayParameter == null ? true : Parameters.Empty) && - (Initializer is ConstructorBaseInitializer) && - (Initializer.Arguments == null); - } - - // - // Creates the ConstructorBuilder - // - public override bool Define (TypeContainer parent) - { - MethodAttributes ca = (MethodAttributes.RTSpecialName | - MethodAttributes.SpecialName); - - // Check if arguments were correct. - if (!DoDefineParameters (parent)) - return false; - - if ((ModFlags & Modifiers.STATIC) != 0) - ca |= MethodAttributes.Static; - else { - if (parent is Struct && ParameterTypes.Length == 0){ - Report.Error ( - 568, Location, - "Structs can not contain explicit parameterless " + - "constructors"); - return false; - } - ca |= MethodAttributes.HideBySig; - - if ((ModFlags & Modifiers.PUBLIC) != 0) - ca |= MethodAttributes.Public; - else if ((ModFlags & Modifiers.PROTECTED) != 0){ - if ((ModFlags & Modifiers.INTERNAL) != 0) - ca |= MethodAttributes.FamORAssem; - else - ca |= MethodAttributes.Family; - } else if ((ModFlags & Modifiers.INTERNAL) != 0) - ca |= MethodAttributes.Assembly; - else if (IsDefault ()) - ca |= MethodAttributes.Public; - else - ca |= MethodAttributes.Private; - } - - ConstructorBuilder = parent.TypeBuilder.DefineConstructor ( - ca, GetCallingConvention (parent is Class), ParameterTypes); - - // - // HACK because System.Reflection.Emit is lame - // - if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) { - Report.Error ( - 111, Location, - "Class `" +parent.Name+ "' already contains a definition with the " + - "same return value and parameter types for constructor `" + Name - + "'"); - return false; - } - - return true; - } - - // - // Emits the code - // - public void Emit (TypeContainer parent) - { - ILGenerator ig = ConstructorBuilder.GetILGenerator (); - EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true); - - // - // extern methods have no bodies - // - if ((ModFlags & Modifiers.EXTERN) != 0) { - if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) { - Report.Error ( - 179, Location, "External constructor `" + - TypeManager.CSharpSignature (ConstructorBuilder) + - "' can not have a body"); - return; - } - } else if (block == null) { - Report.Error ( - 501, Location, "Constructor `" + - TypeManager.CSharpSignature (ConstructorBuilder) + - "' must declare a body since it is not marked extern"); - return; - } - - if ((ModFlags & Modifiers.STATIC) == 0){ - if (parent is Class && Initializer == null) - Initializer = new ConstructorBaseInitializer ( - null, Parameters.EmptyReadOnlyParameters, parent.Location); - - - // - // Spec mandates that Initializers will not have - // `this' access - // - ec.IsStatic = true; - if (Initializer != null && !Initializer.Resolve (ec)) - return; - ec.IsStatic = false; - } - - LabelParameters (ec, ParameterTypes, ConstructorBuilder); - - // - // Classes can have base initializers and instance field initializers. - // - if (parent is Class){ - if ((ModFlags & Modifiers.STATIC) == 0) - parent.EmitFieldInitializers (ec); - } - if (Initializer != null) - Initializer.Emit (ec); - - if ((ModFlags & Modifiers.STATIC) != 0) - parent.EmitFieldInitializers (ec); - - Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location); - - // If this is a non-static `struct' constructor and doesn't have any - // initializer, it must initialize all of the struct's fields. - if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && - (Initializer == null)) - Block.AddThisVariable (parent, Location); - - ec.EmitTopBlock (Block, ParameterInfo, Location); - } - } - - public class MethodData { - // - // The return type of this method - // - public readonly Type ReturnType; - public readonly Type[] ParameterTypes; - public readonly InternalParameters ParameterInfo; - public readonly CallingConventions CallingConventions; - public readonly Attributes OptAttributes; - public readonly Location Location; - - // - // Are we implementing an interface ? - // - public bool IsImplementing = false; - - // - // Protected data. - // - protected MemberBase member; - protected int modifiers; - protected MethodAttributes flags; - protected bool is_method; - protected string accessor_name; - ArrayList conditionals; - - MethodBuilder builder = null; - public MethodBuilder MethodBuilder { - get { - return builder; - } - } - - public MethodData (MemberBase member, string name, Type return_type, - Type [] parameter_types, InternalParameters parameters, - CallingConventions cc, Attributes opt_attrs, - int modifiers, MethodAttributes flags, bool is_method) - { - this.member = member; - this.accessor_name = name; - this.ReturnType = return_type; - this.ParameterTypes = parameter_types; - this.ParameterInfo = parameters; - this.CallingConventions = cc; - this.OptAttributes = opt_attrs; - this.modifiers = modifiers; - this.flags = flags; - this.is_method = is_method; - this.Location = member.Location; - this.conditionals = new ArrayList (); - } - - // - // Attributes. - // - Attribute dllimport_attribute = null; - string obsolete = null; - bool obsolete_error = false; - - public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method) - { - if ((opt_attrs == null) || (opt_attrs.AttributeSections == null)) - return true; - - foreach (AttributeSection asec in opt_attrs.AttributeSections) { - if (asec.Attributes == null) - continue; - - foreach (Attribute a in asec.Attributes) { - if (a.Name == "Conditional") { - if (!ApplyConditionalAttribute (a)) - return false; - } else if (a.Name == "Obsolete") { - if (!ApplyObsoleteAttribute (a)) - return false; - } else if (a.Name.IndexOf ("DllImport") != -1) { - if (!is_method) { - a.Type = TypeManager.dllimport_type; - Attribute.Error_AttributeNotValidForElement (a, Location); - return false; - } - if (!ApplyDllImportAttribute (a)) - return false; - } - } - } - - return true; - } - - // - // Applies the `DllImport' attribute to the method. - // - protected virtual bool ApplyDllImportAttribute (Attribute a) - { - const int extern_static = Modifiers.EXTERN | Modifiers.STATIC; - if ((modifiers & extern_static) != extern_static) { - Report.Error (601, Location, - "The DllImport attribute must be specified on a method " + - "marked `static' and `extern'."); - return false; - } - - flags |= MethodAttributes.PinvokeImpl; - dllimport_attribute = a; - return true; - } - - // - // Applies the `Obsolete' attribute to the method. - // - protected virtual bool ApplyObsoleteAttribute (Attribute a) - { - if (obsolete != null) { - Report.Error (579, Location, "Duplicate `Obsolete' attribute"); - return false; - } - - obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error); - return obsolete != null; - } - - // - // Applies the `Conditional' attribute to the method. - // - protected virtual bool ApplyConditionalAttribute (Attribute a) - { - // The Conditional attribute is only valid on methods. - if (!is_method) { - Attribute.Error_AttributeNotValidForElement (a, Location); - return false; - } - - string condition = a.Conditional_GetConditionName (); - - if (condition == null) - return false; - - if (ReturnType != TypeManager.void_type) { - Report.Error (578, Location, - "Conditional not valid on `" + member.Name + "' " + - "because its return type is not void"); - return false; - } - - if ((modifiers & Modifiers.OVERRIDE) != 0) { - Report.Error (243, Location, - "Conditional not valid on `" + member.Name + "' " + - "because it is an override method"); - return false; - } - - if (member.IsExplicitImpl) { - Report.Error (577, Location, - "Conditional not valid on `" + member.Name + "' " + - "because it is an explicit interface implementation"); - return false; - } - - if (IsImplementing) { - Report.Error (623, Location, - "Conditional not valid on `" + member.Name + "' " + - "because it is an interface method"); - return false; - } - - conditionals.Add (condition); - - return true; - } - - // - // Checks whether this method should be ignored due to its Conditional attributes. - // - bool ShouldIgnore (Location loc) - { - // When we're overriding a virtual method, we implicitly inherit the - // Conditional attributes from our parent. - if (member.ParentMethod != null) { - TypeManager.MethodFlags flags = TypeManager.GetMethodFlags ( - member.ParentMethod, loc); - - if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0) - return true; - } - - foreach (string condition in conditionals) - if (RootContext.AllDefines [condition] == null) - return true; - - return false; - } - - // - // Returns the TypeManager.MethodFlags for this method. - // This emits an error 619 / warning 618 if the method is obsolete. - // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned. - // - public virtual TypeManager.MethodFlags GetMethodFlags (Location loc) - { - TypeManager.MethodFlags flags = 0; - - if (obsolete != null) { - if (obsolete_error) { - Report.Error (619, loc, "Method `" + member.Name + - "' is obsolete: `" + obsolete + "'"); - return TypeManager.MethodFlags.IsObsoleteError; - } else - Report.Warning (618, loc, "Method `" + member.Name + - "' is obsolete: `" + obsolete + "'"); - - flags |= TypeManager.MethodFlags.IsObsolete; - } - - if (ShouldIgnore (loc)) - flags |= TypeManager.MethodFlags.ShouldIgnore; - - return flags; - } - - public virtual bool Define (TypeContainer parent) - { - MethodInfo implementing = null; - string method_name, name, prefix; - - if (OptAttributes != null) - if (!ApplyAttributes (OptAttributes, is_method)) - return false; - - if (member.IsExplicitImpl) - prefix = member.InterfaceType.FullName + "."; - else - prefix = ""; - - if (accessor_name != null) - name = accessor_name + "_" + member.ShortName; - else - name = member.ShortName; - method_name = prefix + name; - - if (parent.Pending != null){ - if (member is Indexer) - implementing = parent.Pending.IsInterfaceIndexer ( - member.InterfaceType, ReturnType, ParameterTypes); - else - implementing = parent.Pending.IsInterfaceMethod ( - member.InterfaceType, name, ReturnType, ParameterTypes); - - if (member.InterfaceType != null && implementing == null){ - TypeContainer.Error_ExplicitInterfaceNotMemberInterface ( - Location, name); - return false; - } - } - - // - // For implicit implementations, make sure we are public, for - // explicit implementations, make sure we are private. - // - if (implementing != null){ - // - // Setting null inside this block will trigger a more - // verbose error reporting for missing interface implementations - // - // The "candidate" function has been flagged already - // but it wont get cleared - // - if (!member.IsExplicitImpl){ - // - // We already catch different accessibility settings - // so we just need to check that we are not private - // - if ((modifiers & Modifiers.PRIVATE) != 0) - implementing = null; - - // - // Static is not allowed - // - if ((modifiers & Modifiers.STATIC) != 0) - implementing = null; - } else { - if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){ - Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract"); - implementing = null; - } - } - } - - // - // If implementing is still valid, set flags - // - if (implementing != null){ - // - // When implementing interface methods, set NewSlot. - // - if (implementing.DeclaringType.IsInterface) - flags |= MethodAttributes.NewSlot; - - flags |= - MethodAttributes.Virtual | - MethodAttributes.HideBySig; - - // Get the method name from the explicit interface. - if (member.InterfaceType != null) { - name = implementing.Name; - method_name = prefix + name; - } - - IsImplementing = true; - } - - // - // Create the MethodBuilder for the method - // - if ((flags & MethodAttributes.PinvokeImpl) != 0) { - if ((modifiers & Modifiers.STATIC) == 0) { - Report.Error (601, Location, - "The DllImport attribute must be specified on " + - "a method marked 'static' and 'extern'."); - return false; - } - - EmitContext ec = new EmitContext ( - parent, Location, null, ReturnType, modifiers); - - builder = dllimport_attribute.DefinePInvokeMethod ( - ec, parent.TypeBuilder, method_name, flags, - ReturnType, ParameterTypes); - } else - builder = parent.TypeBuilder.DefineMethod ( - method_name, flags, CallingConventions, - ReturnType, ParameterTypes); - - if (builder == null) - return false; - - if (IsImplementing) { - // - // clear the pending implemntation flag - // - if (member is Indexer) { - parent.Pending.ImplementIndexer ( - member.InterfaceType, builder, ReturnType, - ParameterTypes, true); - } else - parent.Pending.ImplementMethod ( - member.InterfaceType, name, ReturnType, - ParameterTypes, member.IsExplicitImpl); - - if (member.IsExplicitImpl) - parent.TypeBuilder.DefineMethodOverride ( - builder, implementing); - } - - if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) { - Report.Error (111, Location, - "Class `" + parent.Name + - "' already contains a definition with the " + - "same return value and parameter types as the " + - "'get' method of property `" + member.Name + "'"); - return false; - } - - TypeManager.AddMethod (builder, this); - - return true; - } - - // - // Emits the code - // - public virtual void Emit (TypeContainer parent, Block block, object kind) - { - ILGenerator ig; - EmitContext ec; - - if ((flags & MethodAttributes.PinvokeImpl) == 0) - ig = builder.GetILGenerator (); - else - ig = null; - - ec = new EmitContext (parent, Location, ig, ReturnType, modifiers); - - if (OptAttributes != null) - Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location); - - if (member is MethodCore) - ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder); - - // - // abstract or extern methods have no bodies - // - if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){ - if (block == null) - return; - - // - // abstract or extern methods have no bodies. - // - if ((modifiers & Modifiers.ABSTRACT) != 0) - Report.Error ( - 500, Location, "Abstract method `" + - TypeManager.CSharpSignature (builder) + - "' can not have a body"); - - if ((modifiers & Modifiers.EXTERN) != 0) - Report.Error ( - 179, Location, "External method `" + - TypeManager.CSharpSignature (builder) + - "' can not have a body"); - - return; - } - - // - // Methods must have a body unless they're extern or abstract - // - if (block == null) { - Report.Error ( - 501, Location, "Method `" + - TypeManager.CSharpSignature (builder) + - "' must declare a body since it is not marked " + - "abstract or extern"); - return; - } - - // - // Handle destructors specially - // - // FIXME: This code generates buggy code - // - if (member.Name == "Finalize" && ReturnType == TypeManager.void_type) - EmitDestructor (ec, block); - else { - ISymbolWriter sw = CodeGen.SymbolWriter; - - if ((sw != null) && !Location.IsNull (Location) && - !Location.IsNull (block.EndLocation)) { - Location end = block.EndLocation; - MethodToken token = MethodBuilder.GetToken (); - sw.OpenMethod (new SymbolToken (token.Token)); - // Avoid error if we don't support debugging for the platform - try { - sw.SetMethodSourceRange (Location.SymbolDocument, - Location.Row, 0, - end.SymbolDocument, - end.Row, 0); - } catch (Exception) { - } - - ec.EmitTopBlock (block, ParameterInfo, Location); - - sw.CloseMethod (); - } else - ec.EmitTopBlock (block, ParameterInfo, Location); - } - } - - void EmitDestructor (EmitContext ec, Block block) - { - ILGenerator ig = ec.ig; - - Label finish = ig.DefineLabel (); - bool old_in_try = ec.InTry; - - 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) { - Expression member_lookup = Expression.MemberLookup ( - ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType, - "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location); - - if (member_lookup != null){ - MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup); - - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]); - } - } - ec.InFinally = old_in_finally; - - ig.EndExceptionBlock (); - //ig.MarkLabel (ec.ReturnLabel); - ig.Emit (OpCodes.Ret); - } - } - - abstract public class MemberBase : MemberCore { - public Expression Type; - public readonly Attributes OptAttributes; - - protected MethodAttributes flags; - - // - // The "short" name of this property / indexer / event. This is the - // name without the explicit interface. - // - public string ShortName; - - // - // The type of this property / indexer / event - // - public Type MemberType; - - // - // If true, this is an explicit interface implementation - // - public bool IsExplicitImpl = false; - - // - // The name of the interface we are explicitly implementing - // - public string ExplicitInterfaceName = null; - - // - // If true, the interface type we are explicitly implementing - // - public Type InterfaceType = null; - - // - // The method we're overriding if this is an override method. - // - protected MethodInfo parent_method = null; - public MethodInfo ParentMethod { - get { - return parent_method; - } - } - - // - // The constructor is only exposed to our children - // - protected MemberBase (Expression type, int mod, int allowed_mod, string name, - Attributes attrs, Location loc) - : base (name, loc) - { - Type = type; - ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc); - OptAttributes = attrs; - } - - protected virtual bool CheckBase (TypeContainer parent) - { - return true; - } - - protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters) - { - bool error = false; - - foreach (Type partype in parameters){ - if (partype.IsPointer && !UnsafeOK (parent)) - error = true; - - if (parent.AsAccessible (partype, ModFlags)) - continue; - - if (this is Indexer) - Report.Error (55, Location, - "Inconsistent accessibility: parameter type `" + - TypeManager.CSharpName (partype) + "' is less " + - "accessible than indexer `" + Name + "'"); - else - Report.Error (51, Location, - "Inconsistent accessibility: parameter type `" + - TypeManager.CSharpName (partype) + "' is less " + - "accessible than method `" + Name + "'"); - error = true; - } - - return !error; - } - - protected virtual bool DoDefine (TypeContainer parent) - { - if (Name == null) - Name = "this"; - - if (!parent.MethodModifiersValid (ModFlags, Name, Location)) - return false; - - flags = Modifiers.MethodAttr (ModFlags); - - // Lookup Type, verify validity - MemberType = parent.ResolveType (Type, false, Location); - if (MemberType == null) - return false; - - // verify accessibility - if (!parent.AsAccessible (MemberType, ModFlags)) { - if (this is Property) - Report.Error (53, Location, - "Inconsistent accessibility: property type `" + - TypeManager.CSharpName (MemberType) + "' is less " + - "accessible than property `" + Name + "'"); - else if (this is Indexer) - Report.Error (54, Location, - "Inconsistent accessibility: indexer return type `" + - TypeManager.CSharpName (MemberType) + "' is less " + - "accessible than indexer `" + Name + "'"); - else if (this is Method) - Report.Error (50, Location, - "Inconsistent accessibility: return type `" + - TypeManager.CSharpName (MemberType) + "' is less " + - "accessible than method `" + Name + "'"); - else - Report.Error (52, Location, - "Inconsistent accessibility: field type `" + - TypeManager.CSharpName (MemberType) + "' is less " + - "accessible than field `" + Name + "'"); - return false; - } - - if (MemberType.IsPointer && !UnsafeOK (parent)) - return false; - - // - // Check for explicit interface implementation - // - if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){ - int pos = Name.LastIndexOf ("."); - - ExplicitInterfaceName = Name.Substring (0, pos); - ShortName = Name.Substring (pos + 1); - } else - ShortName = Name; - - if (ExplicitInterfaceName != null) { - InterfaceType = RootContext.LookupType ( - parent, ExplicitInterfaceName, false, Location); - if (InterfaceType == null) - return false; - - // Compute the full name that we need to export. - Name = InterfaceType.FullName + "." + ShortName; - - if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location)) - return false; - - IsExplicitImpl = true; - } else - IsExplicitImpl = false; - - return true; - } - } - - // - // Fields and Events both generate FieldBuilders, we use this to share - // their common bits. This is also used to flag usage of the field - // - abstract public class FieldBase : MemberBase { - public FieldBuilder FieldBuilder; - public Status status; - - [Flags] - public enum Status : byte { ASSIGNED = 1, USED = 2 } - - // - // The constructor is only exposed to our children - // - protected FieldBase (Expression type, int mod, int allowed_mod, string name, - object init, Attributes attrs, Location loc) - : base (type, mod, allowed_mod, name, attrs, loc) - { - this.init = init; - } - - // - // Whether this field has an initializer. - // - public bool HasInitializer { - get { - return init != null; - } - } - - // Private. - readonly Object init; - Expression init_expr; - bool init_expr_initialized = false; - - // - // Resolves and returns the field initializer. - // - public Expression GetInitializerExpression (EmitContext ec) - { - if (init_expr_initialized) - return init_expr; - - Expression e; - if (init is Expression) - e = (Expression) init; - else - e = new ArrayCreation (Type, "", (ArrayList)init, Location); - - ec.IsFieldInitializer = true; - e = e.DoResolve (ec); - ec.IsFieldInitializer = false; - - init_expr = e; - init_expr_initialized = true; - - return init_expr; - } - } - - // - // The Field class is used to represents class/struct fields during parsing. - // - public class Field : FieldBase { - // <summary> - // Modifiers allowed in a class declaration - // </summary> - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.VOLATILE | - Modifiers.UNSAFE | - Modifiers.READONLY; - - public Field (Expression type, int mod, string name, Object expr_or_array_init, - Attributes attrs, Location loc) - : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc) - { - } - - public override bool Define (TypeContainer parent) - { - Type t = parent.ResolveType (Type, false, Location); - - if (t == null) - return false; - - if (!parent.AsAccessible (t, ModFlags)) { - Report.Error (52, Location, - "Inconsistent accessibility: field type `" + - TypeManager.CSharpName (t) + "' is less " + - "accessible than field `" + Name + "'"); - return false; - } - - if (t.IsPointer && !UnsafeOK (parent)) - return false; - - if (RootContext.WarningLevel > 1){ - Type ptype = parent.TypeBuilder.BaseType; - - // ptype is only null for System.Object while compiling corlib. - if (ptype != null){ - TypeContainer.FindMembers ( - ptype, MemberTypes.Method, - BindingFlags.Public | - BindingFlags.Static | BindingFlags.Instance, - System.Type.FilterName, Name); - } - } - - if ((ModFlags & Modifiers.VOLATILE) != 0){ - if (!t.IsClass){ - if (TypeManager.IsEnumType (t)) - t = TypeManager.EnumToUnderlying (t); - - if (!((t == TypeManager.bool_type) || - (t == TypeManager.sbyte_type) || - (t == TypeManager.byte_type) || - (t == TypeManager.short_type) || - (t == TypeManager.ushort_type) || - (t == TypeManager.int32_type) || - (t == TypeManager.uint32_type) || - (t == TypeManager.char_type) || - (t == TypeManager.float_type))){ - Report.Error ( - 677, Location, parent.MakeName (Name) + - " A volatile field can not be of type `" + - TypeManager.CSharpName (t) + "'"); - return false; - } - } - } - - FieldAttributes fa = Modifiers.FieldAttr (ModFlags); - - if (parent is Struct && - ((fa & FieldAttributes.Static) == 0) && - t == parent.TypeBuilder && - !TypeManager.IsBuiltinType (t)){ - Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name + - "' causes a cycle in the structure layout"); - return false; - } - FieldBuilder = parent.TypeBuilder.DefineField ( - Name, t, Modifiers.FieldAttr (ModFlags)); - - TypeManager.RegisterFieldBase (FieldBuilder, this); - return true; - } - - public void Emit (TypeContainer tc) - { - EmitContext ec = new EmitContext (tc, Location, null, - FieldBuilder.FieldType, ModFlags); - - Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location); - } - } - - // - // `set' and `get' accessors are represented with an Accessor. - // - public class Accessor { - // - // Null if the accessor is empty, or a Block if not - // - public Block Block; - public Attributes OptAttributes; - - public Accessor (Block b, Attributes attrs) - { - Block = b; - OptAttributes = attrs; - } - } - - // - // Properties and Indexers both generate PropertyBuilders, we use this to share - // their common bits. - // - abstract public class PropertyBase : MethodCore { - public Accessor Get, Set; - public PropertyBuilder PropertyBuilder; - public MethodBuilder GetBuilder, SetBuilder; - public MethodData GetData, SetData; - - protected EmitContext ec; - - public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod, - Parameters parameters, Accessor get_block, Accessor set_block, - Attributes attrs, Location loc) - : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc) - { - Get = get_block; - Set = set_block; - } - - protected override bool DoDefine (TypeContainer parent) - { - if (!base.DoDefine (parent)) - return false; - - ec = new EmitContext (parent, Location, null, MemberType, ModFlags); - - return true; - } - - // - // Checks our base implementation if any - // - protected override bool CheckBase (TypeContainer parent) - { - // Check whether arguments were correct. - if (!DoDefineParameters (parent)) - return false; - - if (IsExplicitImpl) - return true; - - string report_name; - MethodSignature ms, base_ms; - if (this is Indexer) { - string name, base_name; - - report_name = "this"; - name = TypeManager.IndexerPropertyName (parent.TypeBuilder); - ms = new MethodSignature (name, null, ParameterTypes); - base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType); - base_ms = new MethodSignature (base_name, null, ParameterTypes); - } else { - report_name = Name; - ms = base_ms = new MethodSignature (Name, null, ParameterTypes); - } - - // - // Verify if the parent has a type with the same name, and then - // check whether we have to create a new slot for it or not. - // - Type ptype = parent.TypeBuilder.BaseType; - - // ptype is only null for System.Object while compiling corlib. - if (ptype == null) { - if ((ModFlags & Modifiers.NEW) != 0) - WarningNotHiding (parent); - - return true; - } - - MemberList props_this; - - props_this = TypeContainer.FindMembers ( - parent.TypeBuilder, MemberTypes.Property, - BindingFlags.NonPublic | BindingFlags.Public | - BindingFlags.Static | BindingFlags.Instance | - BindingFlags.DeclaredOnly, - MethodSignature.method_signature_filter, ms); - - if (props_this.Count > 0) { - Report.Error (111, Location, "Class `" + parent.Name + "' " + - "already defines a member called `" + report_name + "' " + - "with the same parameter types"); - return false; - } - - MemberList mi_props; - - mi_props = TypeContainer.FindMembers ( - ptype, MemberTypes.Property, - BindingFlags.NonPublic | BindingFlags.Public | - BindingFlags.Instance | BindingFlags.Static, - MethodSignature.inheritable_method_signature_filter, base_ms); - - if (mi_props.Count > 0){ - PropertyInfo parent_property = (PropertyInfo) mi_props [0]; - string name = parent_property.DeclaringType.Name + "." + - parent_property.Name; - - MethodInfo get, set, parent_method; - get = parent_property.GetGetMethod (true); - set = parent_property.GetSetMethod (true); - - if (get != null) - parent_method = get; - else if (set != null) - parent_method = set; - else - throw new Exception ("Internal error!"); - - if (!CheckMethodAgainstBase (parent, flags, parent_method, name)) - return false; - - if ((ModFlags & Modifiers.NEW) == 0) { - Type parent_type = TypeManager.TypeToCoreType ( - parent_property.PropertyType); - - if (parent_type != MemberType) { - Report.Error ( - 508, parent.MakeName (Name) + ": cannot " + - "change return type when overriding " + - "inherited member " + name); - return false; - } - } - } else { - if ((ModFlags & Modifiers.NEW) != 0) - WarningNotHiding (parent); - - if ((ModFlags & Modifiers.OVERRIDE) != 0){ - if (this is Indexer) - Report.Error (115, Location, - parent.MakeName (Name) + - " no suitable indexers found to override"); - else - Report.Error (115, Location, - parent.MakeName (Name) + - " no suitable properties found to override"); - return false; - } - } - return true; - } - - public void Emit (TypeContainer tc) - { - // - // The PropertyBuilder can be null for explicit implementations, in that - // case, we do not actually emit the ".property", so there is nowhere to - // put the attribute - // - if (PropertyBuilder != null) - Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location); - - if (GetData != null) - GetData.Emit (tc, Get.Block, Get); - - if (SetData != null) - SetData.Emit (tc, Set.Block, Set); - } - } - - public class Property : PropertyBase { - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.ABSTRACT | - Modifiers.UNSAFE | - Modifiers.EXTERN | - Modifiers.VIRTUAL; - - public Property (Expression type, string name, int mod_flags, - Accessor get_block, Accessor set_block, - Attributes attrs, Location loc) - : base (type, name, mod_flags, AllowedModifiers, - Parameters.EmptyReadOnlyParameters, - get_block, set_block, attrs, loc) - { - } - - public override bool Define (TypeContainer parent) - { - if (!DoDefine (parent)) - return false; - - if (!CheckBase (parent)) - return false; - - flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; - - if (Get != null) { - Type [] parameters = TypeManager.NoTypes; - - InternalParameters ip = new InternalParameters ( - parent, Parameters.EmptyReadOnlyParameters); - - GetData = new MethodData (this, "get", MemberType, - parameters, ip, CallingConventions.Standard, - Get.OptAttributes, ModFlags, flags, false); - - if (!GetData.Define (parent)) - return false; - - GetBuilder = GetData.MethodBuilder; - } - - if (Set != null) { - Type [] parameters = new Type [1]; - parameters [0] = MemberType; - - Parameter [] parms = new Parameter [1]; - parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null); - InternalParameters ip = new InternalParameters ( - parent, new Parameters (parms, null, Location)); - - SetData = new MethodData (this, "set", TypeManager.void_type, - parameters, ip, CallingConventions.Standard, - Set.OptAttributes, ModFlags, flags, false); - - if (!SetData.Define (parent)) - return false; - - SetBuilder = SetData.MethodBuilder; - SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - } - - // FIXME - PropertyAttributes.HasDefault ? - - PropertyAttributes prop_attr = - PropertyAttributes.RTSpecialName | - PropertyAttributes.SpecialName; - - if (!IsExplicitImpl){ - PropertyBuilder = parent.TypeBuilder.DefineProperty ( - Name, prop_attr, MemberType, null); - - if (Get != null) - PropertyBuilder.SetGetMethod (GetBuilder); - - if (Set != null) - PropertyBuilder.SetSetMethod (SetBuilder); - - // - // HACK for the reasons exposed above - // - if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) { - Report.Error ( - 111, Location, - "Class `" + parent.Name + - "' already contains a definition for the property `" + - Name + "'"); - return false; - } - } - return true; - } - } - - /// </summary> - /// Gigantic workaround for lameness in SRE follows : - /// This class derives from EventInfo and attempts to basically - /// wrap around the EventBuilder so that FindMembers can quickly - /// return this in it search for members - /// </summary> - public class MyEventBuilder : EventInfo { - - // - // We use this to "point" to our Builder which is - // not really a MemberInfo - // - EventBuilder MyBuilder; - - // - // We "catch" and wrap these methods - // - MethodInfo raise, remove, add; - - EventAttributes attributes; - Type declaring_type, reflected_type, event_type; - string name; - - Event my_event; - - public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type) - { - MyBuilder = type_builder.DefineEvent (name, event_attr, event_type); - - // And now store the values in our own fields. - - declaring_type = type_builder; - - reflected_type = type_builder; - - attributes = event_attr; - this.name = name; - my_event = ev; - this.event_type = event_type; - } - - // - // Methods that you have to override. Note that you only need - // to "implement" the variants that take the argument (those are - // the "abstract" methods, the others (GetAddMethod()) are - // regular. - // - public override MethodInfo GetAddMethod (bool nonPublic) - { - return add; - } - - public override MethodInfo GetRemoveMethod (bool nonPublic) - { - return remove; - } - - public override MethodInfo GetRaiseMethod (bool nonPublic) - { - return raise; - } - - // - // These methods make "MyEventInfo" look like a Builder - // - public void SetRaiseMethod (MethodBuilder raiseMethod) - { - raise = raiseMethod; - MyBuilder.SetRaiseMethod (raiseMethod); - } - - public void SetRemoveOnMethod (MethodBuilder removeMethod) - { - remove = removeMethod; - MyBuilder.SetRemoveOnMethod (removeMethod); - } - - public void SetAddOnMethod (MethodBuilder addMethod) - { - add = addMethod; - MyBuilder.SetAddOnMethod (addMethod); - } - - public void SetCustomAttribute (CustomAttributeBuilder cb) - { - MyBuilder.SetCustomAttribute (cb); - } - - public override object [] GetCustomAttributes (bool inherit) - { - // FIXME : There's nothing which can be seemingly done here because - // we have no way of getting at the custom attribute objects of the - // EventBuilder ! - return null; - } - - public override object [] GetCustomAttributes (Type t, bool inherit) - { - // FIXME : Same here ! - return null; - } - - public override bool IsDefined (Type t, bool b) - { - return true; - } - - public override EventAttributes Attributes { - get { - return attributes; - } - } - - public override string Name { - get { - return name; - } - } - - public override Type DeclaringType { - get { - return declaring_type; - } - } - - public override Type ReflectedType { - get { - return reflected_type; - } - } - - public Type EventType { - get { - return event_type; - } - } - - public void SetUsed () - { - if (my_event != null) - my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED); - } - } - - public class Event : FieldBase { - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.VIRTUAL | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.UNSAFE | - Modifiers.ABSTRACT; - - public readonly Accessor Add; - public readonly Accessor Remove; - public MyEventBuilder EventBuilder; - - MethodBuilder AddBuilder, RemoveBuilder; - MethodData AddData, RemoveData; - - public Event (Expression type, string name, Object init, int mod, Accessor add, - Accessor remove, Attributes attrs, Location loc) - : base (type, mod, AllowedModifiers, name, init, attrs, loc) - { - Add = add; - Remove = remove; - } - - public override bool Define (TypeContainer parent) - { - EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName; - - if (!DoDefine (parent)) - return false; - - if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) { - Report.Error (66, Location, "'" + parent.Name + "." + Name + - "' : event must be of a delegate type"); - return false; - } - - Type [] parameter_types = new Type [1]; - parameter_types [0] = MemberType; - - Parameter [] parms = new Parameter [1]; - parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null); - InternalParameters ip = new InternalParameters ( - parent, new Parameters (parms, null, Location)); - - if (!CheckBase (parent)) - return false; - - // - // Now define the accessors - // - AddData = new MethodData (this, "add", TypeManager.void_type, - parameter_types, ip, CallingConventions.Standard, - (Add != null) ? Add.OptAttributes : null, - ModFlags, flags, false); - - if (!AddData.Define (parent)) - return false; - - AddBuilder = AddData.MethodBuilder; - AddBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - - RemoveData = new MethodData (this, "remove", TypeManager.void_type, - parameter_types, ip, CallingConventions.Standard, - (Remove != null) ? Remove.OptAttributes : null, - ModFlags, flags, false); - - if (!RemoveData.Define (parent)) - return false; - - RemoveBuilder = RemoveData.MethodBuilder; - RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - - if (!IsExplicitImpl){ - EventBuilder = new MyEventBuilder (this, - parent.TypeBuilder, Name, e_attr, MemberType); - - if (Add == null && Remove == null) { - FieldBuilder = parent.TypeBuilder.DefineField ( - Name, MemberType, - FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0)); - TypeManager.RegisterPrivateFieldOfEvent ( - (EventInfo) EventBuilder, FieldBuilder); - TypeManager.RegisterFieldBase (FieldBuilder, this); - } - - EventBuilder.SetAddOnMethod (AddBuilder); - EventBuilder.SetRemoveOnMethod (RemoveBuilder); - - if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) { - Report.Error (111, Location, - "Class `" + parent.Name + - "' already contains a definition for the event `" + - Name + "'"); - return false; - } - } - - return true; - } - - void EmitDefaultMethod (EmitContext ec, bool is_add) - { - ILGenerator ig = ec.ig; - MethodInfo method = null; - - if (is_add) - method = TypeManager.delegate_combine_delegate_delegate; - else - method = TypeManager.delegate_remove_delegate_delegate; - - if ((ModFlags & Modifiers.STATIC) != 0) { - ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder); - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Call, method); - ig.Emit (OpCodes.Castclass, MemberType); - ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder); - } else { - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder); - ig.Emit (OpCodes.Ldarg_1); - ig.Emit (OpCodes.Call, method); - ig.Emit (OpCodes.Castclass, MemberType); - ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder); - } - ig.Emit (OpCodes.Ret); - } - - public void Emit (TypeContainer tc) - { - EmitContext ec; - - ec = new EmitContext (tc, Location, null, MemberType, ModFlags); - Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location); - - if (Add != null) - AddData.Emit (tc, Add.Block, Add); - else { - ILGenerator ig = AddData.MethodBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags); - EmitDefaultMethod (ec, true); - } - - if (Remove != null) - RemoveData.Emit (tc, Remove.Block, Remove); - else { - ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags); - EmitDefaultMethod (ec, false); - } - } - - } - - // - // FIXME: This does not handle: - // - // int INTERFACENAME [ args ] - // Does not - // - // Only: - // - // int this [ args ] - - public class Indexer : PropertyBase { - - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.VIRTUAL | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.UNSAFE | - Modifiers.EXTERN | - Modifiers.ABSTRACT; - - public string IndexerName; - public string InterfaceIndexerName; - - // - // Are we implementing an interface ? - // - bool IsImplementing = false; - - public Indexer (Expression type, string int_type, int flags, Parameters parameters, - Accessor get_block, Accessor set_block, Attributes attrs, Location loc) - : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block, - attrs, loc) - { - ExplicitInterfaceName = int_type; - } - - public override bool Define (TypeContainer parent) - { - PropertyAttributes prop_attr = - PropertyAttributes.RTSpecialName | - PropertyAttributes.SpecialName; - - if (!DoDefine (parent)) - return false; - - IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes); - if (IndexerName == null) - IndexerName = "Item"; - else if (IsExplicitImpl) - Report.Error (592, Location, - "Attribute 'IndexerName' is not valid on this declaration " + - "type. It is valid on `property' declarations only."); - - ShortName = IndexerName; - if (IsExplicitImpl) { - InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType); - Name = InterfaceType.FullName + "." + IndexerName; - } else { - InterfaceIndexerName = IndexerName; - Name = ShortName; - } - - if (!CheckBase (parent)) - return false; - - if (Get != null){ - InternalParameters ip = new InternalParameters (parent, Parameters); - - GetData = new MethodData (this, "get", MemberType, - ParameterTypes, ip, CallingConventions.Standard, - Get.OptAttributes, ModFlags, flags, false); - - if (!GetData.Define (parent)) - return false; - - GetBuilder = GetData.MethodBuilder; - } - - if (Set != null){ - int top = ParameterTypes.Length; - Type [] set_pars = new Type [top + 1]; - ParameterTypes.CopyTo (set_pars, 0); - set_pars [top] = MemberType; - - Parameter [] fixed_parms = Parameters.FixedParameters; - - if (fixed_parms == null){ - throw new Exception ("We currently do not support only array arguments in an indexer"); - // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG - // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG - // - // Here is the problem: the `value' parameter has - // to come *after* the array parameter in the declaration - // like this: - // X (object [] x, Type value) - // .param [0] - // - // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG - // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG - - } - - Parameter [] tmp = new Parameter [fixed_parms.Length + 1]; - - - fixed_parms.CopyTo (tmp, 0); - tmp [fixed_parms.Length] = new Parameter ( - Type, "value", Parameter.Modifier.NONE, null); - - Parameters set_formal_params = new Parameters (tmp, null, Location); - - InternalParameters ip = new InternalParameters (parent, set_formal_params); - - SetData = new MethodData (this, "set", TypeManager.void_type, - set_pars, ip, CallingConventions.Standard, - Set.OptAttributes, ModFlags, flags, false); - - if (!SetData.Define (parent)) - return false; - - SetBuilder = SetData.MethodBuilder; - } - - // - // Now name the parameters - // - Parameter [] p = Parameters.FixedParameters; - if (p != null) { - int i; - - for (i = 0; i < p.Length; ++i) { - if (Get != null) - GetBuilder.DefineParameter ( - i + 1, p [i].Attributes, p [i].Name); - - if (Set != null) - SetBuilder.DefineParameter ( - i + 1, p [i].Attributes, p [i].Name); - } - - if (Set != null) - SetBuilder.DefineParameter ( - i + 1, ParameterAttributes.None, "value"); - - if (i != ParameterTypes.Length) { - Parameter array_param = Parameters.ArrayParameter; - SetBuilder.DefineParameter ( - i + 1, array_param.Attributes, array_param.Name); - } - } - - if (GetData != null) - IsImplementing = GetData.IsImplementing; - else if (SetData != null) - IsImplementing = SetData.IsImplementing; - - // - // Define the PropertyBuilder if one of the following conditions are met: - // a) we're not implementing an interface indexer. - // b) the indexer has a different IndexerName and this is no - // explicit interface implementation. - // - if (!IsExplicitImpl) { - PropertyBuilder = parent.TypeBuilder.DefineProperty ( - IndexerName, prop_attr, MemberType, ParameterTypes); - - if (GetData != null) - PropertyBuilder.SetGetMethod (GetBuilder); - - if (SetData != null) - PropertyBuilder.SetSetMethod (SetBuilder); - - TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, - ParameterTypes); - } - - return true; - } - } - - public class Operator : MemberCore { - - const int AllowedModifiers = - Modifiers.PUBLIC | - Modifiers.UNSAFE | - Modifiers.EXTERN | - Modifiers.STATIC; - - const int RequiredModifiers = - Modifiers.PUBLIC | - Modifiers.STATIC; - - public enum OpType : byte { - - // Unary operators - LogicalNot, - OnesComplement, - Increment, - Decrement, - True, - False, - - // Unary and Binary operators - Addition, - Subtraction, - - UnaryPlus, - UnaryNegation, - - // Binary operators - Multiply, - Division, - Modulus, - BitwiseAnd, - BitwiseOr, - ExclusiveOr, - LeftShift, - RightShift, - Equality, - Inequality, - GreaterThan, - LessThan, - GreaterThanOrEqual, - LessThanOrEqual, - - // Implicit and Explicit - Implicit, - Explicit - }; - - public readonly OpType OperatorType; - public readonly Expression ReturnType; - public readonly Expression FirstArgType, SecondArgType; - public readonly string FirstArgName, SecondArgName; - public readonly Block Block; - public Attributes OptAttributes; - public MethodBuilder OperatorMethodBuilder; - - public string MethodName; - public Method OperatorMethod; - - public Operator (OpType type, Expression ret_type, int flags, - Expression arg1type, string arg1name, - Expression arg2type, string arg2name, - Block block, Attributes attrs, Location loc) - : base ("", loc) - { - OperatorType = type; - ReturnType = ret_type; - ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc); - FirstArgType = arg1type; - FirstArgName = arg1name; - SecondArgType = arg2type; - SecondArgName = arg2name; - Block = block; - OptAttributes = attrs; - } - - string Prototype (TypeContainer parent) - { - return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," + - SecondArgType + ")"; - } - - public override bool Define (TypeContainer parent) - { - int length = 1; - MethodName = "op_" + OperatorType; - - if (SecondArgType != null) - length = 2; - - Parameter [] param_list = new Parameter [length]; - - if ((ModFlags & RequiredModifiers) != RequiredModifiers){ - Report.Error ( - 558, Location, - "User defined operators `" + - Prototype (parent) + - "' must be declared static and public"); - return false; - } - - param_list[0] = new Parameter (FirstArgType, FirstArgName, - Parameter.Modifier.NONE, null); - if (SecondArgType != null) - param_list[1] = new Parameter (SecondArgType, SecondArgName, - Parameter.Modifier.NONE, null); - - OperatorMethod = new Method (ReturnType, ModFlags, MethodName, - new Parameters (param_list, null, Location), - OptAttributes, Mono.CSharp.Location.Null); - - OperatorMethod.IsOperator = true; - OperatorMethod.Define (parent); - - if (OperatorMethod.MethodBuilder == null) - return false; - - OperatorMethodBuilder = OperatorMethod.MethodBuilder; - - Type [] param_types = OperatorMethod.ParameterTypes; - Type declaring_type = OperatorMethodBuilder.DeclaringType; - Type return_type = OperatorMethod.GetReturnType (); - Type first_arg_type = param_types [0]; - - // Rules for conversion operators - - if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { - if (first_arg_type == return_type && first_arg_type == declaring_type){ - Report.Error ( - 555, Location, - "User-defined conversion cannot take an object of the " + - "enclosing type and convert to an object of the enclosing" + - " type"); - return false; - } - - if (first_arg_type != declaring_type && return_type != declaring_type){ - Report.Error ( - 556, Location, - "User-defined conversion must convert to or from the " + - "enclosing type"); - return false; - } - - if (first_arg_type == TypeManager.object_type || - return_type == TypeManager.object_type){ - Report.Error ( - -8, Location, - "User-defined conversion cannot convert to or from " + - "object type"); - return false; - } - - if (first_arg_type.IsInterface || return_type.IsInterface){ - Report.Error ( - 552, Location, - "User-defined conversion cannot convert to or from an " + - "interface type"); - return false; - } - - if (first_arg_type.IsSubclassOf (return_type) || - return_type.IsSubclassOf (first_arg_type)){ - Report.Error ( - -10, Location, - "User-defined conversion cannot convert between types " + - "that derive from each other"); - return false; - } - } else if (SecondArgType == null) { - // Checks for Unary operators - - if (first_arg_type != declaring_type){ - Report.Error ( - 562, Location, - "The parameter of a unary operator must be the " + - "containing type"); - return false; - } - - if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) { - if (return_type != declaring_type){ - Report.Error ( - 559, Location, - "The parameter and return type for ++ and -- " + - "must be the containing type"); - return false; - } - - } - - if (OperatorType == OpType.True || OperatorType == OpType.False) { - if (return_type != TypeManager.bool_type){ - Report.Error ( - 215, Location, - "The return type of operator True or False " + - "must be bool"); - return false; - } - } - - } else { - // Checks for Binary operators - - if (first_arg_type != declaring_type && - param_types [1] != declaring_type){ - Report.Error ( - 563, Location, - "One of the parameters of a binary operator must " + - "be the containing type"); - return false; - } - } - - return true; - } - - public void Emit (TypeContainer parent) - { - EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags); - Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location); - - // - // abstract or extern methods have no bodies - // - if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) - return; - - OperatorMethod.Block = Block; - OperatorMethod.Emit (parent); - } - - public static string GetName (OpType ot) - { - switch (ot){ - case OpType.LogicalNot: - return "!"; - case OpType.OnesComplement: - return "~"; - case OpType.Increment: - return "++"; - case OpType.Decrement: - return "--"; - case OpType.True: - return "true"; - case OpType.False: - return "false"; - case OpType.Addition: - return "+"; - case OpType.Subtraction: - return "-"; - case OpType.UnaryPlus: - return "+"; - case OpType.UnaryNegation: - return "-"; - case OpType.Multiply: - return "*"; - case OpType.Division: - return "/"; - case OpType.Modulus: - return "%"; - case OpType.BitwiseAnd: - return "&"; - case OpType.BitwiseOr: - return "|"; - case OpType.ExclusiveOr: - return "^"; - case OpType.LeftShift: - return "<<"; - case OpType.RightShift: - return ">>"; - case OpType.Equality: - return "=="; - case OpType.Inequality: - return "!="; - case OpType.GreaterThan: - return ">"; - case OpType.LessThan: - return "<"; - case OpType.GreaterThanOrEqual: - return ">="; - case OpType.LessThanOrEqual: - return "<="; - case OpType.Implicit: - return "implicit"; - case OpType.Explicit: - return "explicit"; - default: return ""; - } - } - - public override string ToString () - { - Type return_type = OperatorMethod.GetReturnType(); - Type [] param_types = OperatorMethod.ParameterTypes; - - if (SecondArgType == null) - return String.Format ( - "{0} operator {1}({2})", - TypeManager.CSharpName (return_type), - GetName (OperatorType), - param_types [0]); - else - return String.Format ( - "{0} operator {1}({2}, {3})", - TypeManager.CSharpName (return_type), - GetName (OperatorType), - param_types [0], param_types [1]); - } - } - - // - // This is used to compare method signatures - // - struct MethodSignature { - public string Name; - public Type RetType; - public Type [] Parameters; - - /// <summary> - /// This delegate is used to extract methods which have the - /// same signature as the argument - /// </summary> - public static MemberFilter method_signature_filter; - - /// <summary> - /// This delegate is used to extract inheritable methods which - /// have the same signature as the argument. By inheritable, - /// this means that we have permissions to override the method - /// from the current assembly and class - /// </summary> - public static MemberFilter inheritable_method_signature_filter; - - static MethodSignature () - { - method_signature_filter = new MemberFilter (MemberSignatureCompare); - inheritable_method_signature_filter = new MemberFilter ( - InheritableMemberSignatureCompare); - } - - public MethodSignature (string name, Type ret_type, Type [] parameters) - { - Name = name; - RetType = ret_type; - - if (parameters == null) - Parameters = TypeManager.NoTypes; - else - Parameters = parameters; - } - - public override int GetHashCode () - { - return Name.GetHashCode (); - } - - public override bool Equals (Object o) - { - MethodSignature other = (MethodSignature) o; - - if (other.Name != Name) - return false; - - if (other.RetType != RetType) - return false; - - if (Parameters == null){ - if (other.Parameters == null) - return true; - return false; - } - - if (other.Parameters == null) - return false; - - int c = Parameters.Length; - if (other.Parameters.Length != c) - return false; - - for (int i = 0; i < c; i++) - if (other.Parameters [i] != Parameters [i]) - return false; - - return true; - } - - static bool MemberSignatureCompare (MemberInfo m, object filter_criteria) - { - MethodSignature sig = (MethodSignature) filter_criteria; - - if (m.Name != sig.Name) - return false; - - Type ReturnType; - MethodInfo mi = m as MethodInfo; - PropertyInfo pi = m as PropertyInfo; - - if (mi != null) - ReturnType = mi.ReturnType; - else if (pi != null) - ReturnType = pi.PropertyType; - else - return false; - - // - // we use sig.RetType == null to mean `do not check the - // method return value. - // - if (sig.RetType != null) - if (ReturnType != sig.RetType) - return false; - - Type [] args; - if (mi != null) - args = TypeManager.GetArgumentTypes (mi); - else - args = TypeManager.GetArgumentTypes (pi); - Type [] sigp = sig.Parameters; - - if (args.Length != sigp.Length) - return false; - - for (int i = args.Length; i > 0; ){ - i--; - if (args [i] != sigp [i]) - return false; - } - return true; - } - - // - // This filter should be used when we are requesting methods that - // we want to override. - // - // This makes a number of assumptions, for example - // that the methods being extracted are of a parent - // class (this means we know implicitly that we are - // being called to find out about members by a derived - // class). - // - static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria) - { - if (!MemberSignatureCompare (m, filter_criteria)) - return false; - - MethodInfo mi; - PropertyInfo pi = m as PropertyInfo; - - if (pi != null) { - mi = pi.GetGetMethod (true); - if (mi == null) - mi = pi.GetSetMethod (true); - } else - mi = m as MethodInfo; - - if (mi == null){ - Console.WriteLine ("Nothing found"); - } - - MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask; - - // If only accessible to the current class. - if (prot == MethodAttributes.Private) - return false; - - // If only accessible to the defining assembly or - if (prot == MethodAttributes.FamANDAssem || - prot == MethodAttributes.Assembly){ - if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder) - return true; - else - return false; - } - - // Anything else (FamOrAssembly and Public) is fine - return true; - } - } -} diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs deleted file mode 100755 index 3b770362870..00000000000 --- a/mcs/mcs/expression.cs +++ /dev/null @@ -1,7390 +0,0 @@ -// -// expression.cs: Expression representation for the IL tree. -// -// Author: -// Miguel de Icaza (miguel@ximian.com) -// -// (C) 2001 Ximian, Inc. -// -// -#define USE_OLD - -namespace Mono.CSharp { - using System; - using System.Collections; - using System.Reflection; - using System.Reflection.Emit; - using System.Text; - - /// <summary> - /// This is just a helper class, it is generated by Unary, UnaryMutator - /// when an overloaded method has been found. It just emits the code for a - /// static call. - /// </summary> - public class StaticCallExpr : ExpressionStatement { - ArrayList args; - MethodInfo mi; - - StaticCallExpr (MethodInfo m, ArrayList a, Location l) - { - mi = m; - args = a; - - type = m.ReturnType; - eclass = ExprClass.Value; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - // - // We are born fully resolved - // - return this; - } - - public override void Emit (EmitContext ec) - { - if (args != null) - Invocation.EmitArguments (ec, mi, args); - - ec.ig.Emit (OpCodes.Call, mi); - return; - } - - static public Expression MakeSimpleCall (EmitContext ec, MethodGroupExpr mg, - Expression e, Location loc) - { - ArrayList args; - MethodBase method; - - args = new ArrayList (1); - args.Add (new Argument (e, Argument.AType.Expression)); - method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc); - - if (method == null) - return null; - - return new StaticCallExpr ((MethodInfo) method, args, loc); - } - - public override void EmitStatement (EmitContext ec) - { - Emit (ec); - if (TypeManager.TypeToCoreType (type) != TypeManager.void_type) - ec.ig.Emit (OpCodes.Pop); - } - } - - /// <summary> - /// Unary expressions. - /// </summary> - /// - /// <remarks> - /// Unary implements unary expressions. It derives from - /// ExpressionStatement becuase the pre/post increment/decrement - /// operators can be used in a statement context. - /// </remarks> - public class Unary : Expression { - public enum Operator : byte { - UnaryPlus, UnaryNegation, LogicalNot, OnesComplement, - Indirection, AddressOf, TOP - } - - public Operator Oper; - public Expression Expr; - - public Unary (Operator op, Expression expr, Location loc) - { - this.Oper = op; - this.Expr = expr; - this.loc = loc; - } - - /// <summary> - /// Returns a stringified representation of the Operator - /// </summary> - static public string OperName (Operator oper) - { - switch (oper){ - case Operator.UnaryPlus: - return "+"; - case Operator.UnaryNegation: - return "-"; - case Operator.LogicalNot: - return "!"; - case Operator.OnesComplement: - return "~"; - case Operator.AddressOf: - return "&"; - case Operator.Indirection: - return "*"; - } - - return oper.ToString (); - } - - static string [] oper_names; - - static Unary () - { - oper_names = new string [(int)Operator.TOP]; - - oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus"; - oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation"; - oper_names [(int) Operator.LogicalNot] = "op_LogicalNot"; - oper_names [(int) Operator.OnesComplement] = "op_OnesComplement"; - oper_names [(int) Operator.Indirection] = "op_Indirection"; - oper_names [(int) Operator.AddressOf] = "op_AddressOf"; - } - - void Error23 (Type t) - { - Error ( - 23, "Operator " + OperName (Oper) + - " cannot be applied to operand of type `" + - TypeManager.CSharpName (t) + "'"); - } - - /// <remarks> - /// The result has been already resolved: - /// - /// FIXME: a minus constant -128 sbyte cant be turned into a - /// constant byte. - /// </remarks> - static Expression TryReduceNegative (Constant expr) - { - Expression e = null; - - if (expr is IntConstant) - e = new IntConstant (-((IntConstant) expr).Value); - else if (expr is UIntConstant){ - uint value = ((UIntConstant) expr).Value; - - if (value < 2147483649) - return new IntConstant (-(int)value); - else - e = new LongConstant (value); - } - else if (expr is LongConstant) - e = new LongConstant (-((LongConstant) expr).Value); - else if (expr is ULongConstant){ - ulong value = ((ULongConstant) expr).Value; - - if (value < 9223372036854775809) - return new LongConstant(-(long)value); - } - else if (expr is FloatConstant) - e = new FloatConstant (-((FloatConstant) expr).Value); - else if (expr is DoubleConstant) - e = new DoubleConstant (-((DoubleConstant) expr).Value); - else if (expr is DecimalConstant) - e = new DecimalConstant (-((DecimalConstant) expr).Value); - else if (expr is ShortConstant) - e = new IntConstant (-((ShortConstant) expr).Value); - else if (expr is UShortConstant) - e = new IntConstant (-((UShortConstant) expr).Value); - return e; - } - - // <summary> - // This routine will attempt to simplify the unary expression when the - // argument is a constant. The result is returned in `result' and the - // function returns true or false depending on whether a reduction - // was performed or not - // </summary> - bool Reduce (EmitContext ec, Constant e, out Expression result) - { - Type expr_type = e.Type; - - switch (Oper){ - case Operator.UnaryPlus: - result = e; - return true; - - case Operator.UnaryNegation: - result = TryReduceNegative (e); - return true; - - case Operator.LogicalNot: - if (expr_type != TypeManager.bool_type) { - result = null; - Error23 (expr_type); - return false; - } - - BoolConstant b = (BoolConstant) e; - result = new BoolConstant (!(b.Value)); - return true; - - case Operator.OnesComplement: - if (!((expr_type == TypeManager.int32_type) || - (expr_type == TypeManager.uint32_type) || - (expr_type == TypeManager.int64_type) || - (expr_type == TypeManager.uint64_type) || - (expr_type.IsSubclassOf (TypeManager.enum_type)))){ - result = null; - Error23 (expr_type); - return false; - } - - if (e is EnumConstant){ - EnumConstant enum_constant = (EnumConstant) e; - Expression reduced; - - if (Reduce (ec, enum_constant.Child, out reduced)){ - result = new EnumConstant ((Constant) reduced, enum_constant.Type); - return true; - } else { - result = null; - return false; - } - } - - if (expr_type == TypeManager.int32_type){ - result = new IntConstant (~ ((IntConstant) e).Value); - } else if (expr_type == TypeManager.uint32_type){ - result = new UIntConstant (~ ((UIntConstant) e).Value); - } else if (expr_type == TypeManager.int64_type){ - result = new LongConstant (~ ((LongConstant) e).Value); - } else if (expr_type == TypeManager.uint64_type){ - result = new ULongConstant (~ ((ULongConstant) e).Value); - } else { - result = null; - Error23 (expr_type); - return false; - } - return true; - - case Operator.AddressOf: - result = this; - return false; - - case Operator.Indirection: - result = this; - return false; - } - throw new Exception ("Can not constant fold: " + Oper.ToString()); - } - - Expression ResolveOperator (EmitContext ec) - { - Type expr_type = Expr.Type; - - // - // Step 1: Perform Operator Overload location - // - Expression mg; - string op_name; - - op_name = oper_names [(int) Oper]; - - mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); - - if (mg != null) { - Expression e = StaticCallExpr.MakeSimpleCall ( - ec, (MethodGroupExpr) mg, Expr, loc); - - if (e == null){ - Error23 (expr_type); - return null; - } - - return e; - } - - // Only perform numeric promotions on: - // +, - - - if (expr_type == null) - return null; - - // - // Step 2: Default operations on CLI native types. - // - - // Attempt to use a constant folding operation. - if (Expr is Constant){ - Expression result; - - if (Reduce (ec, (Constant) Expr, out result)) - return result; - } - - switch (Oper){ - case Operator.LogicalNot: - if (expr_type != TypeManager.bool_type) { - Error23 (Expr.Type); - return null; - } - - type = TypeManager.bool_type; - return this; - - case Operator.OnesComplement: - if (!((expr_type == TypeManager.int32_type) || - (expr_type == TypeManager.uint32_type) || - (expr_type == TypeManager.int64_type) || - (expr_type == TypeManager.uint64_type) || - (expr_type.IsSubclassOf (TypeManager.enum_type)))){ - Expression e; - - e = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc); - if (e != null){ - type = TypeManager.int32_type; - return this; - } - e = ConvertImplicit (ec, Expr, TypeManager.uint32_type, loc); - if (e != null){ - type = TypeManager.uint32_type; - return this; - } - e = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc); - if (e != null){ - type = TypeManager.int64_type; - return this; - } - e = ConvertImplicit (ec, Expr, TypeManager.uint64_type, loc); - if (e != null){ - type = TypeManager.uint64_type; - return this; - } - Error23 (expr_type); - return null; - } - type = expr_type; - return this; - - case Operator.AddressOf: - if (Expr.eclass != ExprClass.Variable){ - Error (211, "Cannot take the address of non-variables"); - return null; - } - - if (!ec.InUnsafe) { - UnsafeError (loc); - return null; - } - - if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){ - return null; - } - - string ptr_type_name = Expr.Type.FullName + "*"; - type = TypeManager.LookupType (ptr_type_name); - - return this; - - case Operator.Indirection: - if (!ec.InUnsafe){ - UnsafeError (loc); - return null; - } - - if (!expr_type.IsPointer){ - Error ( - 193, - "The * or -> operator can only be applied to pointers"); - return null; - } - - // - // We create an Indirection expression, because - // it can implement the IMemoryLocation. - // - return new Indirection (Expr, loc); - - case Operator.UnaryPlus: - // - // A plus in front of something is just a no-op, so return the child. - // - return Expr; - - case Operator.UnaryNegation: - // - // Deals with -literals - // int operator- (int x) - // long operator- (long x) - // float operator- (float f) - // double operator- (double d) - // decimal operator- (decimal d) - // - Expression expr = null; - - // - // transform - - expr into expr - // - if (Expr is Unary){ - Unary unary = (Unary) Expr; - - if (unary.Oper == Operator.UnaryNegation) - return unary.Expr; - } - - // - // perform numeric promotions to int, - // long, double. - // - // - // The following is inneficient, because we call - // ConvertImplicit too many times. - // - // It is also not clear if we should convert to Float - // or Double initially. - // - if (expr_type == TypeManager.uint32_type){ - // - // FIXME: handle exception to this rule that - // permits the int value -2147483648 (-2^31) to - // bt wrote as a decimal interger literal - // - type = TypeManager.int64_type; - Expr = ConvertImplicit (ec, Expr, type, loc); - return this; - } - - if (expr_type == TypeManager.uint64_type){ - // - // FIXME: Handle exception of `long value' - // -92233720368547758087 (-2^63) to be wrote as - // decimal integer literal. - // - Error23 (expr_type); - return null; - } - - if (expr_type == TypeManager.float_type){ - type = expr_type; - return this; - } - - expr = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc); - if (expr != null){ - Expr = expr; - type = expr.Type; - return this; - } - - expr = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc); - if (expr != null){ - Expr = expr; - type = expr.Type; - return this; - } - - expr = ConvertImplicit (ec, Expr, TypeManager.double_type, loc); - if (expr != null){ - Expr = expr; - type = expr.Type; - return this; - } - - Error23 (expr_type); - return null; - } - - Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" + - TypeManager.CSharpName (expr_type) + "'"); - return null; - } - - public override Expression DoResolve (EmitContext ec) - { - if (Oper == Operator.AddressOf) - Expr = Expr.ResolveLValue (ec, new EmptyExpression ()); - else - Expr = Expr.Resolve (ec); - - if (Expr == null) - return null; - - eclass = ExprClass.Value; - return ResolveOperator (ec); - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - Type expr_type = Expr.Type; - - switch (Oper) { - case Operator.UnaryPlus: - throw new Exception ("This should be caught by Resolve"); - - case Operator.UnaryNegation: - Expr.Emit (ec); - ig.Emit (OpCodes.Neg); - break; - - case Operator.LogicalNot: - Expr.Emit (ec); - ig.Emit (OpCodes.Ldc_I4_0); - ig.Emit (OpCodes.Ceq); - break; - - case Operator.OnesComplement: - Expr.Emit (ec); - ig.Emit (OpCodes.Not); - break; - - case Operator.AddressOf: - ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore); - break; - - default: - throw new Exception ("This should not happen: Operator = " - + Oper.ToString ()); - } - } - - /// <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) - { - if (Oper != Operator.LogicalNot) - throw new Exception ("EmitLogicalNot can only be called with !expr"); - - Expr.Emit (ec); - } - - public override string ToString () - { - return "Unary (" + Oper + ", " + Expr + ")"; - } - - } - - // - // Unary operators are turned into Indirection expressions - // after semantic analysis (this is so we can take the address - // of an indirection). - // - public class Indirection : Expression, IMemoryLocation, IAssignMethod { - Expression expr; - LocalTemporary temporary; - bool have_temporary; - - public Indirection (Expression expr, Location l) - { - this.expr = expr; - this.type = TypeManager.TypeToCoreType (expr.Type.GetElementType ()); - eclass = ExprClass.Variable; - loc = l; - } - - void LoadExprValue (EmitContext ec) - { - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - if (temporary != null){ - if (have_temporary){ - temporary.Emit (ec); - return; - } - expr.Emit (ec); - ec.ig.Emit (OpCodes.Dup); - temporary.Store (ec); - have_temporary = true; - } else - expr.Emit (ec); - - LoadFromPtr (ig, Type); - } - - public void EmitAssign (EmitContext ec, Expression source) - { - if (temporary != null){ - if (have_temporary){ - temporary.Emit (ec); - return; - } - expr.Emit (ec); - ec.ig.Emit (OpCodes.Dup); - temporary.Store (ec); - have_temporary = true; - } else - expr.Emit (ec); - - source.Emit (ec); - StoreFromPtr (ec.ig, type); - } - - public void AddressOf (EmitContext ec, AddressOp Mode) - { - if (temporary != null){ - if (have_temporary){ - temporary.Emit (ec); - return; - } - expr.Emit (ec); - ec.ig.Emit (OpCodes.Dup); - temporary.Store (ec); - have_temporary = true; - } else - expr.Emit (ec); - } - - public override Expression DoResolve (EmitContext ec) - { - // - // Born fully resolved - // - return this; - } - - public new void CacheTemporaries (EmitContext ec) - { - temporary = new LocalTemporary (ec, type); - } - } - - /// <summary> - /// Unary Mutator expressions (pre and post ++ and --) - /// </summary> - /// - /// <remarks> - /// UnaryMutator implements ++ and -- expressions. It derives from - /// ExpressionStatement becuase the pre/post increment/decrement - /// operators can be used in a statement context. - /// - /// FIXME: Idea, we could split this up in two classes, one simpler - /// for the common case, and one with the extra fields for more complex - /// classes (indexers require temporary access; overloaded require method) - /// - /// </remarks> - public class UnaryMutator : ExpressionStatement { - [Flags] - public enum Mode : byte { - IsIncrement = 0, - IsDecrement = 1, - IsPre = 0, - IsPost = 2, - - PreIncrement = 0, - PreDecrement = IsDecrement, - PostIncrement = IsPost, - PostDecrement = IsPost | IsDecrement - } - - Mode mode; - Expression expr; - LocalTemporary temp_storage; - - // - // This is expensive for the simplest case. - // - Expression method; - - public UnaryMutator (Mode m, Expression e, Location l) - { - mode = m; - loc = l; - expr = e; - } - - static string OperName (Mode mode) - { - return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ? - "++" : "--"; - } - - void Error23 (Type t) - { - Error ( - 23, "Operator " + OperName (mode) + - " cannot be applied to operand of type `" + - TypeManager.CSharpName (t) + "'"); - } - - /// <summary> - /// Returns whether an object of type `t' can be incremented - /// or decremented with add/sub (ie, basically whether we can - /// use pre-post incr-decr operations on it, but it is not a - /// System.Decimal, which we require operator overloading to catch) - /// </summary> - static bool IsIncrementableNumber (Type t) - { - return (t == TypeManager.sbyte_type) || - (t == TypeManager.byte_type) || - (t == TypeManager.short_type) || - (t == TypeManager.ushort_type) || - (t == TypeManager.int32_type) || - (t == TypeManager.uint32_type) || - (t == TypeManager.int64_type) || - (t == TypeManager.uint64_type) || - (t == TypeManager.char_type) || - (t.IsSubclassOf (TypeManager.enum_type)) || - (t == TypeManager.float_type) || - (t == TypeManager.double_type) || - (t.IsPointer && t != TypeManager.void_ptr_type); - } - - Expression ResolveOperator (EmitContext ec) - { - Type expr_type = expr.Type; - - // - // Step 1: Perform Operator Overload location - // - Expression mg; - string op_name; - - if (mode == Mode.PreIncrement || mode == Mode.PostIncrement) - op_name = "op_Increment"; - else - op_name = "op_Decrement"; - - mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); - - if (mg == null && expr_type.BaseType != null) - mg = MemberLookup (ec, expr_type.BaseType, op_name, - MemberTypes.Method, AllBindingFlags, loc); - - if (mg != null) { - method = StaticCallExpr.MakeSimpleCall ( - ec, (MethodGroupExpr) mg, expr, loc); - - type = method.Type; - return this; - } - - // - // The operand of the prefix/postfix increment decrement operators - // should be an expression that is classified as a variable, - // a property access or an indexer access - // - type = expr_type; - if (expr.eclass == ExprClass.Variable){ - if (IsIncrementableNumber (expr_type) || - expr_type == TypeManager.decimal_type){ - return this; - } - } else if (expr.eclass == ExprClass.IndexerAccess){ - IndexerAccess ia = (IndexerAccess) expr; - - temp_storage = new LocalTemporary (ec, expr.Type); - - expr = ia.ResolveLValue (ec, temp_storage); - if (expr == null) - return null; - - return this; - } else if (expr.eclass == ExprClass.PropertyAccess){ - PropertyExpr pe = (PropertyExpr) expr; - - if (pe.VerifyAssignable ()) - return this; - - return null; - } else { - expr.Error118 ("variable, indexer or property access"); - return null; - } - - Error (187, "No such operator '" + OperName (mode) + "' defined for type '" + - TypeManager.CSharpName (expr_type) + "'"); - return null; - } - - public override Expression DoResolve (EmitContext ec) - { - expr = expr.Resolve (ec); - - if (expr == null) - return null; - - eclass = ExprClass.Value; - return ResolveOperator (ec); - } - - static int PtrTypeSize (Type t) - { - return GetTypeSize (t.GetElementType ()); - } - - // - // Loads the proper "1" into the stack based on the type, then it emits the - // opcode for the operation requested - // - void LoadOneAndEmitOp (EmitContext ec, Type t) - { - ILGenerator ig = ec.ig; - - if (t == TypeManager.uint64_type || t == TypeManager.int64_type) - LongConstant.EmitLong (ig, 1); - else if (t == TypeManager.double_type) - ig.Emit (OpCodes.Ldc_R8, 1.0); - else if (t == TypeManager.float_type) - ig.Emit (OpCodes.Ldc_R4, 1.0F); - else if (t.IsPointer){ - int n = PtrTypeSize (t); - - if (n == 0) - ig.Emit (OpCodes.Sizeof, t); - else - IntConstant.EmitInt (ig, n); - } else - ig.Emit (OpCodes.Ldc_I4_1); - - // - // Now emit the operation - // - if (ec.CheckState){ - if (t == TypeManager.int32_type || - t == TypeManager.int64_type){ - if ((mode & Mode.IsDecrement) != 0) - ig.Emit (OpCodes.Sub_Ovf); - else - ig.Emit (OpCodes.Add_Ovf); - } else if (t == TypeManager.uint32_type || - t == TypeManager.uint64_type){ - if ((mode & Mode.IsDecrement) != 0) - ig.Emit (OpCodes.Sub_Ovf_Un); - else - ig.Emit (OpCodes.Add_Ovf_Un); - } else { - if ((mode & Mode.IsDecrement) != 0) - ig.Emit (OpCodes.Sub_Ovf); - else - ig.Emit (OpCodes.Add_Ovf); - } - } else { - if ((mode & Mode.IsDecrement) != 0) - ig.Emit (OpCodes.Sub); - else - ig.Emit (OpCodes.Add); - } - } - - void EmitCode (EmitContext ec, bool is_expr) - { - ILGenerator ig = ec.ig; - IAssignMethod ia = (IAssignMethod) expr; - Type expr_type = expr.Type; - - ia.CacheTemporaries (ec); - - if (temp_storage == null) - temp_storage = new LocalTemporary (ec, expr_type); - - switch (mode){ - case Mode.PreIncrement: - case Mode.PreDecrement: - if (method == null){ - expr.Emit (ec); - - LoadOneAndEmitOp (ec, expr_type); - } else - method.Emit (ec); - - temp_storage.Store (ec); - ia.EmitAssign (ec, temp_storage); - if (is_expr) - temp_storage.Emit (ec); - break; - - case Mode.PostIncrement: - case Mode.PostDecrement: - if (is_expr) - expr.Emit (ec); - - if (method == null){ - if (!is_expr) - expr.Emit (ec); - else - ig.Emit (OpCodes.Dup); - - LoadOneAndEmitOp (ec, expr_type); - } else { - method.Emit (ec); - } - - temp_storage.Store (ec); - ia.EmitAssign (ec, temp_storage); - break; - } - } - - public override void Emit (EmitContext ec) - { - EmitCode (ec, true); - - } - - public override void EmitStatement (EmitContext ec) - { - EmitCode (ec, false); - } - - } - - /// <summary> - /// Base class for the `Is' and `As' classes. - /// </summary> - /// - /// <remarks> - /// FIXME: Split this in two, and we get to save the `Operator' Oper - /// size. - /// </remarks> - public abstract class Probe : Expression { - public readonly Expression ProbeType; - protected Expression expr; - protected Type probe_type; - - public Probe (Expression expr, Expression probe_type, Location l) - { - ProbeType = probe_type; - loc = l; - this.expr = expr; - } - - public Expression Expr { - get { - return expr; - } - } - - public override Expression DoResolve (EmitContext ec) - { - probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc); - - if (probe_type == null) - return null; - - expr = expr.Resolve (ec); - - return this; - } - } - - /// <summary> - /// Implementation of the `is' operator. - /// </summary> - public class Is : Probe { - public Is (Expression expr, Expression probe_type, Location l) - : base (expr, probe_type, l) - { - } - - enum Action { - AlwaysTrue, AlwaysNull, AlwaysFalse, LeaveOnStack, Probe - } - - Action action; - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - expr.Emit (ec); - - switch (action){ - case Action.AlwaysFalse: - ig.Emit (OpCodes.Pop); - IntConstant.EmitInt (ig, 0); - return; - case Action.AlwaysTrue: - ig.Emit (OpCodes.Pop); - IntConstant.EmitInt (ig, 1); - return; - case Action.LeaveOnStack: - // the `e != null' rule. - return; - case Action.Probe: - ig.Emit (OpCodes.Isinst, probe_type); - ig.Emit (OpCodes.Ldnull); - ig.Emit (OpCodes.Cgt_Un); - return; - } - throw new Exception ("never reached"); - } - - public override Expression DoResolve (EmitContext ec) - { - Expression e = base.DoResolve (ec); - - if ((e == null) || (expr == null)) - return null; - - Type etype = expr.Type; - bool warning_always_matches = false; - bool warning_never_matches = false; - - type = TypeManager.bool_type; - eclass = ExprClass.Value; - - // - // First case, if at compile time, there is an implicit conversion - // then e != null (objects) or true (value types) - // - e = ConvertImplicitStandard (ec, expr, probe_type, loc); - if (e != null){ - expr = e; - if (etype.IsValueType) - action = Action.AlwaysTrue; - else - action = Action.LeaveOnStack; - - warning_always_matches = true; - } else if (ExplicitReferenceConversionExists (etype, probe_type)){ - // - // Second case: explicit reference convresion - // - if (expr is NullLiteral) - action = Action.AlwaysFalse; - else - action = Action.Probe; - } else { - action = Action.AlwaysFalse; - warning_never_matches = true; - } - - if (RootContext.WarningLevel >= 1){ - if (warning_always_matches) - Warning ( - 183, - "The expression is always of type `" + - TypeManager.CSharpName (probe_type) + "'"); - else if (warning_never_matches){ - if (!(probe_type.IsInterface || expr.Type.IsInterface)) - Warning ( - 184, - "The expression is never of type `" + - TypeManager.CSharpName (probe_type) + "'"); - } - } - - return this; - } - } - - /// <summary> - /// Implementation of the `as' operator. - /// </summary> - public class As : Probe { - public As (Expression expr, Expression probe_type, Location l) - : base (expr, probe_type, l) - { - } - - bool do_isinst = false; - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - expr.Emit (ec); - - if (do_isinst) - ig.Emit (OpCodes.Isinst, probe_type); - } - - static void Error_CannotConvertType (Type source, Type target, Location loc) - { - Report.Error ( - 39, loc, "as operator can not convert from `" + - TypeManager.CSharpName (source) + "' to `" + - TypeManager.CSharpName (target) + "'"); - } - - public override Expression DoResolve (EmitContext ec) - { - Expression e = base.DoResolve (ec); - - if (e == null) - return null; - - type = probe_type; - eclass = ExprClass.Value; - Type etype = expr.Type; - - if (TypeManager.IsValueType (probe_type)){ - Report.Error (77, loc, "The as operator should be used with a reference type only (" + - TypeManager.CSharpName (probe_type) + " is a value type"); - return null; - - } - - e = ConvertImplicit (ec, expr, probe_type, loc); - if (e != null){ - expr = e; - do_isinst = false; - return this; - } - - if (ExplicitReferenceConversionExists (etype, probe_type)){ - do_isinst = true; - return this; - } - - Error_CannotConvertType (etype, probe_type, loc); - return null; - } - } - - /// <summary> - /// This represents a typecast in the source language. - /// - /// FIXME: Cast expressions have an unusual set of parsing - /// rules, we need to figure those out. - /// </summary> - public class Cast : Expression { - Expression target_type; - Expression expr; - - public Cast (Expression cast_type, Expression expr, Location loc) - { - this.target_type = cast_type; - this.expr = expr; - this.loc = loc; - } - - public Expression TargetType { - get { - return target_type; - } - } - - public Expression Expr { - get { - return expr; - } - set { - expr = value; - } - } - - bool CheckRange (EmitContext ec, long value, Type type, long min, long max) - { - if (!ec.ConstantCheckState) - return true; - - if ((value < min) || (value > max)) { - Error (221, "Constant value `" + value + "' cannot be converted " + - "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " + - "syntax to override)"); - return false; - } - - return true; - } - - bool CheckRange (EmitContext ec, ulong value, Type type, ulong max) - { - if (!ec.ConstantCheckState) - return true; - - if (value > max) { - Error (221, "Constant value `" + value + "' cannot be converted " + - "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " + - "syntax to override)"); - return false; - } - - return true; - } - - bool CheckUnsigned (EmitContext ec, long value, Type type) - { - if (!ec.ConstantCheckState) - return true; - - if (value < 0) { - Error (221, "Constant value `" + value + "' cannot be converted " + - "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " + - "syntax to override)"); - return false; - } - - return true; - } - - /// <summary> - /// Attempts to do a compile-time folding of a constant cast. - /// </summary> - Expression TryReduce (EmitContext ec, Type target_type) - { - if (expr is ByteConstant){ - byte v = ((ByteConstant) expr).Value; - - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) v); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is SByteConstant){ - sbyte v = ((SByteConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UShortConstant ((ushort) v); - } if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UIntConstant ((uint) v); - } if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is ShortConstant){ - short v = ((ShortConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is UShortConstant){ - ushort v = ((UShortConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is IntConstant){ - int v = ((IntConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.uint32_type) { - if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is UIntConstant){ - uint v = ((UIntConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) { - if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue)) - return null; - return new IntConstant ((int) v); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is LongConstant){ - long v = ((LongConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) { - if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue)) - return null; - return new IntConstant ((int) v); - } - if (target_type == TypeManager.uint32_type) { - if (!CheckRange (ec, v, target_type, UInt32.MinValue, UInt32.MaxValue)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.uint64_type) { - if (!CheckUnsigned (ec, v, target_type)) - return null; - return new ULongConstant ((ulong) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is ULongConstant){ - ulong v = ((ULongConstant) expr).Value; - - if (target_type == TypeManager.byte_type) { - if (!CheckRange (ec, v, target_type, Byte.MaxValue)) - return null; - return new ByteConstant ((byte) v); - } - if (target_type == TypeManager.sbyte_type) { - if (!CheckRange (ec, v, target_type, (ulong) SByte.MaxValue)) - return null; - return new SByteConstant ((sbyte) v); - } - if (target_type == TypeManager.short_type) { - if (!CheckRange (ec, v, target_type, (ulong) Int16.MaxValue)) - return null; - return new ShortConstant ((short) v); - } - if (target_type == TypeManager.ushort_type) { - if (!CheckRange (ec, v, target_type, UInt16.MaxValue)) - return null; - return new UShortConstant ((ushort) v); - } - if (target_type == TypeManager.int32_type) { - if (!CheckRange (ec, v, target_type, Int32.MaxValue)) - return null; - return new IntConstant ((int) v); - } - if (target_type == TypeManager.uint32_type) { - if (!CheckRange (ec, v, target_type, UInt32.MaxValue)) - return null; - return new UIntConstant ((uint) v); - } - if (target_type == TypeManager.int64_type) { - if (!CheckRange (ec, v, target_type, (ulong) Int64.MaxValue)) - return null; - return new LongConstant ((long) v); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) { - if (!CheckRange (ec, v, target_type, Char.MaxValue)) - return null; - return new CharConstant ((char) v); - } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is FloatConstant){ - float v = ((FloatConstant) expr).Value; - - if (target_type == TypeManager.byte_type) - return new ByteConstant ((byte) v); - if (target_type == TypeManager.sbyte_type) - return new SByteConstant ((sbyte) v); - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) v); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) v); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - if (expr is DoubleConstant){ - double v = ((DoubleConstant) expr).Value; - - if (target_type == TypeManager.byte_type) - return new ByteConstant ((byte) v); - if (target_type == TypeManager.sbyte_type) - return new SByteConstant ((sbyte) v); - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) v); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) v); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) v); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) v); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) v); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v); - } - - return null; - } - - public override Expression DoResolve (EmitContext ec) - { - expr = expr.Resolve (ec); - if (expr == null) - return null; - - int errors = Report.Errors; - - type = ec.DeclSpace.ResolveType (target_type, false, Location); - - if (type == null) - return null; - - eclass = ExprClass.Value; - - if (expr is Constant){ - Expression e = TryReduce (ec, type); - - if (e != null) - return e; - } - - expr = ConvertExplicit (ec, expr, type, loc); - return expr; - } - - public override void Emit (EmitContext ec) - { - // - // This one will never happen - // - throw new Exception ("Should not happen"); - } - } - - /// <summary> - /// Binary operators - /// </summary> - public class Binary : Expression { - public enum Operator : byte { - Multiply, Division, Modulus, - Addition, Subtraction, - LeftShift, RightShift, - LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, - Equality, Inequality, - BitwiseAnd, - ExclusiveOr, - BitwiseOr, - LogicalAnd, - LogicalOr, - TOP - } - - Operator oper; - Expression left, right; - - // - // After resolution, method might contain the operator overload - // method. - // - protected MethodBase method; - ArrayList Arguments; - - bool DelegateOperation; - - // This must be kept in sync with Operator!!! - static string [] oper_names; - - static Binary () - { - oper_names = new string [(int) Operator.TOP]; - - oper_names [(int) Operator.Multiply] = "op_Multiply"; - oper_names [(int) Operator.Division] = "op_Division"; - oper_names [(int) Operator.Modulus] = "op_Modulus"; - oper_names [(int) Operator.Addition] = "op_Addition"; - oper_names [(int) Operator.Subtraction] = "op_Subtraction"; - oper_names [(int) Operator.LeftShift] = "op_LeftShift"; - oper_names [(int) Operator.RightShift] = "op_RightShift"; - oper_names [(int) Operator.LessThan] = "op_LessThan"; - oper_names [(int) Operator.GreaterThan] = "op_GreaterThan"; - oper_names [(int) Operator.LessThanOrEqual] = "op_LessThanOrEqual"; - oper_names [(int) Operator.GreaterThanOrEqual] = "op_GreaterThanOrEqual"; - oper_names [(int) Operator.Equality] = "op_Equality"; - oper_names [(int) Operator.Inequality] = "op_Inequality"; - oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd"; - oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr"; - oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr"; - oper_names [(int) Operator.LogicalOr] = "op_LogicalOr"; - oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd"; - } - - public Binary (Operator oper, Expression left, Expression right, Location loc) - { - this.oper = oper; - this.left = left; - this.right = right; - this.loc = loc; - } - - public Operator Oper { - get { - return oper; - } - set { - oper = value; - } - } - - public Expression Left { - get { - return left; - } - set { - left = value; - } - } - - public Expression Right { - get { - return right; - } - set { - right = value; - } - } - - - /// <summary> - /// Returns a stringified representation of the Operator - /// </summary> - static string OperName (Operator oper) - { - switch (oper){ - case Operator.Multiply: - return "*"; - case Operator.Division: - return "/"; - case Operator.Modulus: - return "%"; - case Operator.Addition: - return "+"; - case Operator.Subtraction: - return "-"; - case Operator.LeftShift: - return "<<"; - case Operator.RightShift: - return ">>"; - case Operator.LessThan: - return "<"; - case Operator.GreaterThan: - return ">"; - case Operator.LessThanOrEqual: - return "<="; - case Operator.GreaterThanOrEqual: - return ">="; - case Operator.Equality: - return "=="; - case Operator.Inequality: - return "!="; - case Operator.BitwiseAnd: - return "&"; - case Operator.BitwiseOr: - return "|"; - case Operator.ExclusiveOr: - return "^"; - case Operator.LogicalOr: - return "||"; - case Operator.LogicalAnd: - return "&&"; - } - - return oper.ToString (); - } - - public override string ToString () - { - return "operator " + OperName (oper) + "(" + left.ToString () + ", " + - right.ToString () + ")"; - } - - Expression ForceConversion (EmitContext ec, Expression expr, Type target_type) - { - if (expr.Type == target_type) - return expr; - - return ConvertImplicit (ec, expr, target_type, loc); - } - - public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r) - { - Report.Error ( - 34, loc, "Operator `" + OperName (oper) - + "' is ambiguous on operands of type `" - + TypeManager.CSharpName (l) + "' " - + "and `" + TypeManager.CSharpName (r) - + "'"); - } - - bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions) - { - if ((l == t) || (r == t)) - return true; - - if (!check_user_conversions) - return false; - - if (ImplicitUserConversionExists (ec, l, t)) - return true; - else if (ImplicitUserConversionExists (ec, r, t)) - return true; - else - return false; - } - - // - // Note that handling the case l == Decimal || r == Decimal - // is taken care of by the Step 1 Operator Overload resolution. - // - // If `check_user_conv' is true, we also check whether a user-defined conversion - // exists. Note that we only need to do this if both arguments are of a user-defined - // type, otherwise ConvertImplict() already finds the user-defined conversion for us, - // so we don't explicitly check for performance reasons. - // - bool DoNumericPromotions (EmitContext ec, Type l, Type r, bool check_user_conv) - { - if (IsOfType (ec, l, r, TypeManager.double_type, check_user_conv)){ - // - // If either operand is of type double, the other operand is - // conveted to type double. - // - if (r != TypeManager.double_type) - right = ConvertImplicit (ec, right, TypeManager.double_type, loc); - if (l != TypeManager.double_type) - left = ConvertImplicit (ec, left, TypeManager.double_type, loc); - - type = TypeManager.double_type; - } else if (IsOfType (ec, l, r, TypeManager.float_type, check_user_conv)){ - // - // if either operand is of type float, the other operand is - // converted to type float. - // - if (r != TypeManager.double_type) - right = ConvertImplicit (ec, right, TypeManager.float_type, loc); - if (l != TypeManager.double_type) - left = ConvertImplicit (ec, left, TypeManager.float_type, loc); - type = TypeManager.float_type; - } else if (IsOfType (ec, l, r, TypeManager.uint64_type, check_user_conv)){ - Expression e; - Type other; - // - // If either operand is of type ulong, the other operand is - // converted to type ulong. or an error ocurrs if the other - // operand is of type sbyte, short, int or long - // - if (l == TypeManager.uint64_type){ - if (r != TypeManager.uint64_type){ - if (right is IntConstant){ - IntConstant ic = (IntConstant) right; - - e = TryImplicitIntConversion (l, ic); - if (e != null) - right = e; - } else if (right is LongConstant){ - long ll = ((LongConstant) right).Value; - - if (ll > 0) - right = new ULongConstant ((ulong) ll); - } else { - e = ImplicitNumericConversion (ec, right, l, loc); - if (e != null) - right = e; - } - } - other = right.Type; - } else { - if (left is IntConstant){ - e = TryImplicitIntConversion (r, (IntConstant) left); - if (e != null) - left = e; - } else if (left is LongConstant){ - long ll = ((LongConstant) left).Value; - - if (ll > 0) - left = new ULongConstant ((ulong) ll); - } else { - e = ImplicitNumericConversion (ec, left, r, loc); - if (e != null) - left = e; - } - other = left.Type; - } - - if ((other == TypeManager.sbyte_type) || - (other == TypeManager.short_type) || - (other == TypeManager.int32_type) || - (other == TypeManager.int64_type)) - Error_OperatorAmbiguous (loc, oper, l, r); - type = TypeManager.uint64_type; - } else if (IsOfType (ec, l, r, TypeManager.int64_type, check_user_conv)){ - // - // If either operand is of type long, the other operand is converted - // to type long. - // - if (l != TypeManager.int64_type) - left = ConvertImplicit (ec, left, TypeManager.int64_type, loc); - if (r != TypeManager.int64_type) - right = ConvertImplicit (ec, right, TypeManager.int64_type, loc); - - type = TypeManager.int64_type; - } else if (IsOfType (ec, l, r, TypeManager.uint32_type, check_user_conv)){ - // - // If either operand is of type uint, and the other - // operand is of type sbyte, short or int, othe operands are - // converted to type long. - // - Type other = null; - - if (l == TypeManager.uint32_type){ - if (right is IntConstant){ - IntConstant ic = (IntConstant) right; - int val = ic.Value; - - if (val >= 0) - right = new UIntConstant ((uint) val); - - type = l; - return true; - } - other = r; - } - else if (r == TypeManager.uint32_type){ - if (left is IntConstant){ - IntConstant ic = (IntConstant) left; - int val = ic.Value; - - if (val >= 0) - left = new UIntConstant ((uint) val); - - type = r; - return true; - } - - other = l; - } - - if ((other == TypeManager.sbyte_type) || - (other == TypeManager.short_type) || - (other == TypeManager.int32_type)){ - left = ForceConversion (ec, left, TypeManager.int64_type); - right = ForceConversion (ec, right, TypeManager.int64_type); - type = TypeManager.int64_type; - } else { - // - // if either operand is of type uint, the other - // operand is converd to type uint - // - left = ForceConversion (ec, left, TypeManager.uint32_type); - right = ForceConversion (ec, right, TypeManager.uint32_type); - type = TypeManager.uint32_type; - } - } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){ - if (l != TypeManager.decimal_type) - left = ConvertImplicit (ec, left, TypeManager.decimal_type, loc); - - if (r != TypeManager.decimal_type) - right = ConvertImplicit (ec, right, TypeManager.decimal_type, loc); - type = TypeManager.decimal_type; - } else { - left = ForceConversion (ec, left, TypeManager.int32_type); - right = ForceConversion (ec, right, TypeManager.int32_type); - - type = TypeManager.int32_type; - } - - return (left != null) && (right != null); - } - - static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r) - { - Report.Error (19, loc, - "Operator " + name + " cannot be applied to operands of type `" + - TypeManager.CSharpName (l) + "' and `" + - TypeManager.CSharpName (r) + "'"); - } - - void Error_OperatorCannotBeApplied () - { - Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type); - } - - static bool is_32_or_64 (Type t) - { - return (t == TypeManager.int32_type || t == TypeManager.uint32_type || - t == TypeManager.int64_type || t == TypeManager.uint64_type); - } - - static bool is_unsigned (Type t) - { - return (t == TypeManager.uint32_type || t == TypeManager.uint64_type || - t == TypeManager.short_type || t == TypeManager.byte_type); - } - - static bool is_user_defined (Type t) - { - if (t.IsSubclassOf (TypeManager.value_type) && - (!TypeManager.IsBuiltinType (t) || t == TypeManager.decimal_type)) - return true; - else - return false; - } - - Expression CheckShiftArguments (EmitContext ec) - { - Expression e; - Type l = left.Type; - Type r = right.Type; - - e = ForceConversion (ec, right, TypeManager.int32_type); - if (e == null){ - Error_OperatorCannotBeApplied (); - return null; - } - right = e; - - if (((e = ConvertImplicit (ec, left, TypeManager.int32_type, loc)) != null) || - ((e = ConvertImplicit (ec, left, TypeManager.uint32_type, loc)) != null) || - ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) || - ((e = ConvertImplicit (ec, left, TypeManager.uint64_type, loc)) != null)){ - left = e; - type = e.Type; - - return this; - } - Error_OperatorCannotBeApplied (); - return null; - } - - Expression ResolveOperator (EmitContext ec) - { - Type l = left.Type; - Type r = right.Type; - - bool overload_failed = false; - - // - // Special cases: string comapred to null - // - if (oper == Operator.Equality || oper == Operator.Inequality){ - if ((l == TypeManager.string_type && (right is NullLiteral)) || - (r == TypeManager.string_type && (left is NullLiteral))){ - Type = TypeManager.bool_type; - - return this; - } - } - - // - // Do not perform operator overload resolution when both sides are - // built-in types - // - if (!(TypeManager.IsCLRType (l) && TypeManager.IsCLRType (r))){ - // - // Step 1: Perform Operator Overload location - // - Expression left_expr, right_expr; - - string op = oper_names [(int) oper]; - - MethodGroupExpr union; - left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc); - if (r != l){ - right_expr = MemberLookup ( - ec, r, op, MemberTypes.Method, AllBindingFlags, loc); - union = Invocation.MakeUnionSet (left_expr, right_expr, loc); - } else - union = (MethodGroupExpr) left_expr; - - if (union != null) { - Arguments = new ArrayList (); - Arguments.Add (new Argument (left, Argument.AType.Expression)); - Arguments.Add (new Argument (right, Argument.AType.Expression)); - - method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null); - if (method != null) { - MethodInfo mi = (MethodInfo) method; - - type = mi.ReturnType; - return this; - } else { - overload_failed = true; - } - } - } - - // - // Step 2: Default operations on CLI native types. - // - - // - // Step 0: String concatenation (because overloading will get this wrong) - // - if (oper == Operator.Addition){ - // - // If any of the arguments is a string, cast to string - // - - if (l == TypeManager.string_type){ - - if (r == TypeManager.void_type) { - Error_OperatorCannotBeApplied (); - return null; - } - - if (r == TypeManager.string_type){ - if (left is Constant && right is Constant){ - StringConstant ls = (StringConstant) left; - StringConstant rs = (StringConstant) right; - - return new StringConstant ( - ls.Value + rs.Value); - } - - if (left is Binary){ - Binary b = (Binary) left; - - // - // Call String.Concat (string, string, string) or - // String.Concat (string, string, string, string) - // if possible. - // - if (b.oper == Operator.Addition && - (b.method == TypeManager.string_concat_string_string_string || - b.method == TypeManager.string_concat_string_string_string_string)){ - ArrayList bargs = b.Arguments; - int count = bargs.Count; - - if (count == 2){ - Arguments = bargs; - Arguments.Add (new Argument (right, Argument.AType.Expression)); - type = TypeManager.string_type; - method = TypeManager.string_concat_string_string_string; - - return this; - } else if (count == 3){ - Arguments = bargs; - Arguments.Add (new Argument (right, Argument.AType.Expression)); - type = TypeManager.string_type; - method = TypeManager.string_concat_string_string_string_string; - return this; - } - } - } - - // string + string - method = TypeManager.string_concat_string_string; - } else { - // string + object - method = TypeManager.string_concat_object_object; - right = ConvertImplicit (ec, right, - TypeManager.object_type, loc); - if (right == null){ - Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); - return null; - } - } - type = TypeManager.string_type; - - Arguments = new ArrayList (); - Arguments.Add (new Argument (left, Argument.AType.Expression)); - Arguments.Add (new Argument (right, Argument.AType.Expression)); - - return this; - - } else if (r == TypeManager.string_type){ - // object + string - - if (l == TypeManager.void_type) { - Error_OperatorCannotBeApplied (); - return null; - } - - method = TypeManager.string_concat_object_object; - left = ConvertImplicit (ec, left, TypeManager.object_type, loc); - if (left == null){ - Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); - return null; - } - Arguments = new ArrayList (); - Arguments.Add (new Argument (left, Argument.AType.Expression)); - Arguments.Add (new Argument (right, Argument.AType.Expression)); - - type = TypeManager.string_type; - - return this; - } - - // - // Transform a + ( - b) into a - b - // - if (right is Unary){ - Unary right_unary = (Unary) right; - - if (right_unary.Oper == Unary.Operator.UnaryNegation){ - oper = Operator.Subtraction; - right = right_unary.Expr; - r = right.Type; - } - } - } - - if (oper == Operator.Equality || oper == Operator.Inequality){ - if (l == TypeManager.bool_type || r == TypeManager.bool_type){ - if (r != TypeManager.bool_type || l != TypeManager.bool_type){ - Error_OperatorCannotBeApplied (); - return null; - } - - type = TypeManager.bool_type; - return this; - } - - // - // operator != (object a, object b) - // operator == (object a, object b) - // - // For this to be used, both arguments have to be reference-types. - // Read the rationale on the spec (14.9.6) - // - // Also, if at compile time we know that the classes do not inherit - // one from the other, then we catch the error there. - // - if (!(l.IsValueType || r.IsValueType)){ - type = TypeManager.bool_type; - - if (l == r) - return this; - - if (l.IsSubclassOf (r) || r.IsSubclassOf (l)) - return this; - - // - // Also, a standard conversion must exist from either one - // - if (!(StandardConversionExists (left, r) || - StandardConversionExists (right, l))){ - Error_OperatorCannotBeApplied (); - return null; - } - // - // We are going to have to convert to an object to compare - // - if (l != TypeManager.object_type) - left = new EmptyCast (left, TypeManager.object_type); - if (r != TypeManager.object_type) - right = new EmptyCast (right, TypeManager.object_type); - - // - // FIXME: CSC here catches errors cs254 and cs252 - // - return this; - } - - // - // One of them is a valuetype, but the other one is not. - // - if (!l.IsValueType || !r.IsValueType) { - Error_OperatorCannotBeApplied (); - return null; - } - } - - // Only perform numeric promotions on: - // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >= - // - if (oper == Operator.Addition || oper == Operator.Subtraction) { - if (l.IsSubclassOf (TypeManager.delegate_type) && - r.IsSubclassOf (TypeManager.delegate_type)) { - - Arguments = new ArrayList (); - Arguments.Add (new Argument (left, Argument.AType.Expression)); - Arguments.Add (new Argument (right, Argument.AType.Expression)); - - if (oper == Operator.Addition) - method = TypeManager.delegate_combine_delegate_delegate; - else - method = TypeManager.delegate_remove_delegate_delegate; - - if (l != r) { - Error_OperatorCannotBeApplied (); - return null; - } - - DelegateOperation = true; - type = l; - return this; - } - - // - // Pointer arithmetic: - // - // T* operator + (T* x, int y); - // T* operator + (T* x, uint y); - // T* operator + (T* x, long y); - // T* operator + (T* x, ulong y); - // - // T* operator + (int y, T* x); - // T* operator + (uint y, T *x); - // T* operator + (long y, T *x); - // T* operator + (ulong y, T *x); - // - // T* operator - (T* x, int y); - // T* operator - (T* x, uint y); - // T* operator - (T* x, long y); - // T* operator - (T* x, ulong y); - // - // long operator - (T* x, T *y) - // - if (l.IsPointer){ - if (r.IsPointer && oper == Operator.Subtraction){ - if (r == l) - return new PointerArithmetic ( - false, left, right, TypeManager.int64_type, - loc); - } else if (is_32_or_64 (r)) - return new PointerArithmetic ( - oper == Operator.Addition, left, right, l, loc); - } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition) - return new PointerArithmetic ( - true, right, left, r, loc); - } - - // - // Enumeration operators - // - bool lie = TypeManager.IsEnumType (l); - bool rie = TypeManager.IsEnumType (r); - if (lie || rie){ - Expression temp; - - // U operator - (E e, E f) - if (lie && rie && oper == Operator.Subtraction){ - if (l == r){ - type = TypeManager.EnumToUnderlying (l); - return this; - } - Error_OperatorCannotBeApplied (); - return null; - } - - // - // operator + (E e, U x) - // operator - (E e, U x) - // - if (oper == Operator.Addition || oper == Operator.Subtraction){ - Type enum_type = lie ? l : r; - Type other_type = lie ? r : l; - Type underlying_type = TypeManager.EnumToUnderlying (enum_type); -; - - if (underlying_type != other_type){ - Error_OperatorCannotBeApplied (); - return null; - } - - type = enum_type; - return this; - } - - if (!rie){ - temp = ConvertImplicit (ec, right, l, loc); - if (temp != null) - right = temp; - else { - Error_OperatorCannotBeApplied (); - return null; - } - } if (!lie){ - temp = ConvertImplicit (ec, left, r, loc); - if (temp != null){ - left = temp; - l = r; - } else { - Error_OperatorCannotBeApplied (); - return null; - } - } - - if (oper == Operator.Equality || oper == Operator.Inequality || - oper == Operator.LessThanOrEqual || oper == Operator.LessThan || - oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){ - type = TypeManager.bool_type; - return this; - } - - if (oper == Operator.BitwiseAnd || - oper == Operator.BitwiseOr || - oper == Operator.ExclusiveOr){ - type = l; - return this; - } - Error_OperatorCannotBeApplied (); - return null; - } - - if (oper == Operator.LeftShift || oper == Operator.RightShift) - return CheckShiftArguments (ec); - - if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){ - if (l != TypeManager.bool_type || r != TypeManager.bool_type){ - Error_OperatorCannotBeApplied (); - return null; - } - - type = TypeManager.bool_type; - return this; - } - - // - // operator & (bool x, bool y) - // operator | (bool x, bool y) - // operator ^ (bool x, bool y) - // - if (l == TypeManager.bool_type && r == TypeManager.bool_type){ - if (oper == Operator.BitwiseAnd || - oper == Operator.BitwiseOr || - oper == Operator.ExclusiveOr){ - type = l; - return this; - } - } - - // - // Pointer comparison - // - if (l.IsPointer && r.IsPointer){ - if (oper == Operator.Equality || oper == Operator.Inequality || - oper == Operator.LessThan || oper == Operator.LessThanOrEqual || - oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){ - type = TypeManager.bool_type; - return this; - } - } - - // - // We are dealing with numbers - // - if (overload_failed){ - Error_OperatorCannotBeApplied (); - return null; - } - - // - // This will leave left or right set to null if there is an error - // - bool check_user_conv = is_user_defined (l) && is_user_defined (r); - DoNumericPromotions (ec, l, r, check_user_conv); - if (left == null || right == null){ - Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); - return null; - } - - // - // reload our cached types if required - // - l = left.Type; - r = right.Type; - - if (oper == Operator.BitwiseAnd || - oper == Operator.BitwiseOr || - oper == Operator.ExclusiveOr){ - if (l == r){ - if (!((l == TypeManager.int32_type) || - (l == TypeManager.uint32_type) || - (l == TypeManager.int64_type) || - (l == TypeManager.uint64_type))) - type = l; - } else { - Error_OperatorCannotBeApplied (); - return null; - } - } - - if (oper == Operator.Equality || - oper == Operator.Inequality || - oper == Operator.LessThanOrEqual || - oper == Operator.LessThan || - oper == Operator.GreaterThanOrEqual || - oper == Operator.GreaterThan){ - type = TypeManager.bool_type; - } - - return this; - } - - public override Expression DoResolve (EmitContext ec) - { - left = left.Resolve (ec); - right = right.Resolve (ec); - - if (left == null || right == null) - return null; - - eclass = ExprClass.Value; - - Constant rc = right as Constant; - Constant lc = left as Constant; - - if (rc != null & lc != null){ - Expression e = ConstantFold.BinaryFold ( - ec, oper, lc, rc, loc); - if (e != null) - return e; - } - - return ResolveOperator (ec); - } - - /// <remarks> - /// EmitBranchable is called from Statement.EmitBoolExpression in the - /// context of a conditional bool expression. This function will return - /// false if it is was possible to use EmitBranchable, or true if it was. - /// - /// 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) - { - if (method != null) - return false; - - ILGenerator ig = ec.ig; - - // - // This is more complicated than it looks, but its just to avoid - // duplicated tests: basically, we allow ==, !=, >, <, >= and <= - // 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){ - bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue; - - if (left is NullLiteral){ - 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){ - left.Emit (ec); - if (my_on_true) - ig.Emit (OpCodes.Brtrue, target); - else - ig.Emit (OpCodes.Brfalse, target); - return true; - } 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; - } 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; - } - - } else if (oper == Operator.LogicalAnd){ - if (left is Binary){ - Binary left_binary = (Binary) left; - - 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); - 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; - } - } - // - // 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; - - if (right_binary.EmitBranchable (ec, target, true)) - return true; - } - right.Emit (ec); - ig.Emit (OpCodes.Brtrue, target); - return 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 (); - - if (left_binary.EmitBranchable (ec, tests_end, true)){ - if (right is Binary){ - Binary right_binary = (Binary) right; - - 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; - } - } - } - - return false; - } else if (!(oper == Operator.LessThan || - oper == Operator.GreaterThan || - oper == Operator.LessThanOrEqual || - oper == Operator.GreaterThanOrEqual)) - return false; - - left.Emit (ec); - right.Emit (ec); - - bool isUnsigned = is_unsigned (left.Type); - - switch (oper){ - case Operator.Equality: - if (onTrue) - ig.Emit (OpCodes.Beq, target); - else - ig.Emit (OpCodes.Bne_Un, target); - break; - - case Operator.Inequality: - if (onTrue) - ig.Emit (OpCodes.Bne_Un, target); - else - ig.Emit (OpCodes.Beq, target); - break; - - case Operator.LessThan: - if (onTrue) - if (isUnsigned) - ig.Emit (OpCodes.Blt_Un, target); - else - ig.Emit (OpCodes.Blt, target); - else - if (isUnsigned) - ig.Emit (OpCodes.Bge_Un, target); - else - ig.Emit (OpCodes.Bge, target); - break; - - case Operator.GreaterThan: - if (onTrue) - if (isUnsigned) - ig.Emit (OpCodes.Bgt_Un, target); - else - ig.Emit (OpCodes.Bgt, target); - else - if (isUnsigned) - ig.Emit (OpCodes.Ble_Un, target); - else - ig.Emit (OpCodes.Ble, target); - break; - - case Operator.LessThanOrEqual: - if (onTrue) - if (isUnsigned) - ig.Emit (OpCodes.Ble_Un, target); - else - ig.Emit (OpCodes.Ble, target); - else - if (isUnsigned) - ig.Emit (OpCodes.Bgt_Un, target); - else - ig.Emit (OpCodes.Bgt, target); - break; - - - case Operator.GreaterThanOrEqual: - if (onTrue) - if (isUnsigned) - ig.Emit (OpCodes.Bge_Un, target); - else - ig.Emit (OpCodes.Bge, target); - else - if (isUnsigned) - ig.Emit (OpCodes.Blt_Un, target); - else - ig.Emit (OpCodes.Blt, target); - break; - - default: - return false; - } - - return true; - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - Type l = left.Type; - Type r = right.Type; - OpCode opcode; - - if (method != null) { - - // Note that operators are static anyway - - if (Arguments != null) - Invocation.EmitArguments (ec, method, Arguments); - - if (method is MethodInfo) - ig.Emit (OpCodes.Call, (MethodInfo) method); - else - ig.Emit (OpCodes.Call, (ConstructorInfo) method); - - if (DelegateOperation) - ig.Emit (OpCodes.Castclass, type); - - return; - } - - // - // Handle short-circuit operators differently - // than the rest - // - 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)){ - 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){ - 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)){ - 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); - return; - } - - left.Emit (ec); - right.Emit (ec); - - bool isUnsigned = is_unsigned (left.Type); - switch (oper){ - case Operator.Multiply: - if (ec.CheckState){ - if (l == TypeManager.int32_type || l == TypeManager.int64_type) - opcode = OpCodes.Mul_Ovf; - else if (isUnsigned) - opcode = OpCodes.Mul_Ovf_Un; - else - opcode = OpCodes.Mul; - } else - opcode = OpCodes.Mul; - - break; - - case Operator.Division: - if (isUnsigned) - opcode = OpCodes.Div_Un; - else - opcode = OpCodes.Div; - break; - - case Operator.Modulus: - if (isUnsigned) - opcode = OpCodes.Rem_Un; - else - opcode = OpCodes.Rem; - break; - - case Operator.Addition: - if (ec.CheckState){ - if (l == TypeManager.int32_type || l == TypeManager.int64_type) - opcode = OpCodes.Add_Ovf; - else if (isUnsigned) - opcode = OpCodes.Add_Ovf_Un; - else - opcode = OpCodes.Add; - } else - opcode = OpCodes.Add; - break; - - case Operator.Subtraction: - if (ec.CheckState){ - if (l == TypeManager.int32_type || l == TypeManager.int64_type) - opcode = OpCodes.Sub_Ovf; - else if (isUnsigned) - opcode = OpCodes.Sub_Ovf_Un; - else - opcode = OpCodes.Sub; - } else - opcode = OpCodes.Sub; - break; - - case Operator.RightShift: - if (isUnsigned) - opcode = OpCodes.Shr_Un; - else - opcode = OpCodes.Shr; - break; - - case Operator.LeftShift: - opcode = OpCodes.Shl; - break; - - case Operator.Equality: - opcode = OpCodes.Ceq; - break; - - case Operator.Inequality: - ig.Emit (OpCodes.Ceq); - ig.Emit (OpCodes.Ldc_I4_0); - - opcode = OpCodes.Ceq; - break; - - case Operator.LessThan: - if (isUnsigned) - opcode = OpCodes.Clt_Un; - else - opcode = OpCodes.Clt; - break; - - case Operator.GreaterThan: - if (isUnsigned) - opcode = OpCodes.Cgt_Un; - else - opcode = OpCodes.Cgt; - break; - - case Operator.LessThanOrEqual: - if (isUnsigned) - ig.Emit (OpCodes.Cgt_Un); - else - ig.Emit (OpCodes.Cgt); - ig.Emit (OpCodes.Ldc_I4_0); - - opcode = OpCodes.Ceq; - break; - - case Operator.GreaterThanOrEqual: - if (isUnsigned) - ig.Emit (OpCodes.Clt_Un); - else - ig.Emit (OpCodes.Clt); - - ig.Emit (OpCodes.Ldc_I4_1); - - opcode = OpCodes.Sub; - break; - - case Operator.BitwiseOr: - opcode = OpCodes.Or; - break; - - case Operator.BitwiseAnd: - opcode = OpCodes.And; - break; - - case Operator.ExclusiveOr: - opcode = OpCodes.Xor; - break; - - default: - throw new Exception ("This should not happen: Operator = " - + oper.ToString ()); - } - - ig.Emit (opcode); - } - - public bool IsBuiltinOperator { - get { - return method == null; - } - } - } - - public class PointerArithmetic : Expression { - Expression left, right; - bool is_add; - - // - // We assume that `l' is always a pointer - // - public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t, - Location loc) - { - type = t; - eclass = ExprClass.Variable; - this.loc = loc; - left = l; - right = r; - is_add = is_addition; - } - - public override Expression DoResolve (EmitContext ec) - { - // - // We are born fully resolved - // - return this; - } - - public override void Emit (EmitContext ec) - { - Type op_type = left.Type; - ILGenerator ig = ec.ig; - int size = GetTypeSize (op_type.GetElementType ()); - - if (right.Type.IsPointer){ - // - // handle (pointer - pointer) - // - left.Emit (ec); - right.Emit (ec); - ig.Emit (OpCodes.Sub); - - if (size != 1){ - if (size == 0) - ig.Emit (OpCodes.Sizeof, op_type); - else - IntLiteral.EmitInt (ig, size); - ig.Emit (OpCodes.Div); - } - ig.Emit (OpCodes.Conv_I8); - } else { - // - // handle + and - on (pointer op int) - // - left.Emit (ec); - ig.Emit (OpCodes.Conv_I); - right.Emit (ec); - if (size != 1){ - if (size == 0) - ig.Emit (OpCodes.Sizeof, op_type); - else - IntLiteral.EmitInt (ig, size); - ig.Emit (OpCodes.Mul); - } - if (is_add) - ig.Emit (OpCodes.Add); - else - ig.Emit (OpCodes.Sub); - } - } - } - - /// <summary> - /// Implements the ternary conditional operator (?:) - /// </summary> - public class Conditional : Expression { - Expression expr, trueExpr, falseExpr; - - public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l) - { - this.expr = expr; - this.trueExpr = trueExpr; - this.falseExpr = falseExpr; - this.loc = l; - } - - public Expression Expr { - get { - return expr; - } - } - - public Expression TrueExpr { - get { - return trueExpr; - } - } - - public Expression FalseExpr { - get { - return falseExpr; - } - } - - public override Expression DoResolve (EmitContext ec) - { - expr = expr.Resolve (ec); - - if (expr == null) - return null; - - if (expr.Type != TypeManager.bool_type) - expr = Expression.ConvertImplicitRequired ( - ec, expr, TypeManager.bool_type, loc); - - trueExpr = trueExpr.Resolve (ec); - falseExpr = falseExpr.Resolve (ec); - - if (trueExpr == null || falseExpr == null) - return null; - - eclass = ExprClass.Value; - if (trueExpr.Type == falseExpr.Type) - type = trueExpr.Type; - else { - Expression conv; - Type true_type = trueExpr.Type; - Type false_type = falseExpr.Type; - - if (trueExpr is NullLiteral){ - type = false_type; - return this; - } else if (falseExpr is NullLiteral){ - type = true_type; - return this; - } - - // - // First, if an implicit conversion exists from trueExpr - // to falseExpr, then the result type is of type falseExpr.Type - // - conv = ConvertImplicit (ec, trueExpr, false_type, loc); - if (conv != null){ - // - // Check if both can convert implicitl to each other's type - // - if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){ - Error (172, - "Can not compute type of conditional expression " + - "as `" + TypeManager.CSharpName (trueExpr.Type) + - "' and `" + TypeManager.CSharpName (falseExpr.Type) + - "' convert implicitly to each other"); - return null; - } - type = false_type; - trueExpr = conv; - } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){ - type = true_type; - falseExpr = conv; - } else { - Error (173, "The type of the conditional expression can " + - "not be computed because there is no implicit conversion" + - " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" + - " and `" + TypeManager.CSharpName (falseExpr.Type) + "'"); - return null; - } - } - - if (expr is BoolConstant){ - BoolConstant bc = (BoolConstant) expr; - - if (bc.Value) - return trueExpr; - else - return falseExpr; - } - - return this; - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - Label false_target = ig.DefineLabel (); - Label end_target = ig.DefineLabel (); - - Statement.EmitBoolExpression (ec, expr, false_target, false); - trueExpr.Emit (ec); - ig.Emit (OpCodes.Br, end_target); - ig.MarkLabel (false_target); - falseExpr.Emit (ec); - ig.MarkLabel (end_target); - } - - } - - /// <summary> - /// Local variables - /// </summary> - public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable { - public readonly string Name; - public readonly Block Block; - VariableInfo variable_info; - bool is_readonly; - - public LocalVariableReference (Block block, string name, Location l) - { - Block = block; - Name = name; - loc = l; - eclass = ExprClass.Variable; - } - - // Setting `is_readonly' to false will allow you to create a writable - // reference to a read-only variable. This is used by foreach and using. - public LocalVariableReference (Block block, string name, Location l, - VariableInfo variable_info, bool is_readonly) - : this (block, name, l) - { - this.variable_info = variable_info; - this.is_readonly = is_readonly; - } - - public VariableInfo VariableInfo { - get { - if (variable_info == null) { - variable_info = Block.GetVariableInfo (Name); - is_readonly = variable_info.ReadOnly; - } - return variable_info; - } - } - - public bool IsAssigned (EmitContext ec, Location loc) - { - return VariableInfo.IsAssigned (ec, loc); - } - - public bool IsFieldAssigned (EmitContext ec, string name, Location loc) - { - return VariableInfo.IsFieldAssigned (ec, name, loc); - } - - public void SetAssigned (EmitContext ec) - { - VariableInfo.SetAssigned (ec); - } - - public void SetFieldAssigned (EmitContext ec, string name) - { - VariableInfo.SetFieldAssigned (ec, name); - } - - public bool IsReadOnly { - get { - if (variable_info == null) { - variable_info = Block.GetVariableInfo (Name); - is_readonly = variable_info.ReadOnly; - } - return is_readonly; - } - } - - public override Expression DoResolve (EmitContext ec) - { - VariableInfo vi = VariableInfo; - Expression e; - - e = Block.GetConstantExpression (Name); - if (e != null) { - vi.Used = true; - return e; - } - - if (ec.DoFlowAnalysis && !IsAssigned (ec, loc)) - return null; - - type = vi.VariableType; - return this; - } - - override public Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - VariableInfo vi = VariableInfo; - - if (ec.DoFlowAnalysis) - ec.SetVariableAssigned (vi); - - Expression e = DoResolve (ec); - - if (e == null) - return null; - - if (is_readonly){ - Error (1604, "cannot assign to `" + Name + "' because it is readonly"); - return null; - } - - return this; - } - - public override void Emit (EmitContext ec) - { - VariableInfo vi = VariableInfo; - ILGenerator ig = ec.ig; - - ig.Emit (OpCodes.Ldloc, vi.LocalBuilder); - vi.Used = true; - } - - public void EmitAssign (EmitContext ec, Expression source) - { - ILGenerator ig = ec.ig; - VariableInfo vi = VariableInfo; - - vi.Assigned = true; - - source.Emit (ec); - - ig.Emit (OpCodes.Stloc, vi.LocalBuilder); - } - - public void AddressOf (EmitContext ec, AddressOp mode) - { - VariableInfo vi = VariableInfo; - - ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder); - } - } - - /// <summary> - /// This represents a reference to a parameter in the intermediate - /// representation. - /// </summary> - public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable { - Parameters pars; - String name; - int idx; - public Parameter.Modifier mod; - public bool is_ref, is_out; - - public ParameterReference (Parameters pars, int idx, string name, Location loc) - { - this.pars = pars; - this.idx = idx; - this.name = name; - this.loc = loc; - eclass = ExprClass.Variable; - } - - public bool IsAssigned (EmitContext ec, Location loc) - { - if (!is_out || !ec.DoFlowAnalysis) - return true; - - if (!ec.CurrentBranching.IsParameterAssigned (idx)) { - Report.Error (165, loc, - "Use of unassigned local variable `" + name + "'"); - return false; - } - - return true; - } - - public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc) - { - if (!is_out || !ec.DoFlowAnalysis) - return true; - - if (ec.CurrentBranching.IsParameterAssigned (idx)) - return true; - - if (!ec.CurrentBranching.IsParameterAssigned (idx, field_name)) { - Report.Error (170, loc, - "Use of possibly unassigned field `" + field_name + "'"); - return false; - } - - return true; - } - - public void SetAssigned (EmitContext ec) - { - if (is_out && ec.DoFlowAnalysis) - ec.CurrentBranching.SetParameterAssigned (idx); - } - - public void SetFieldAssigned (EmitContext ec, string field_name) - { - if (is_out && ec.DoFlowAnalysis) - ec.CurrentBranching.SetParameterAssigned (idx, field_name); - } - - // - // Notice that for ref/out parameters, the type exposed is not the - // same type exposed externally. - // - // for "ref int a": - // externally we expose "int&" - // here we expose "int". - // - // We record this in "is_ref". This means that the type system can treat - // the type as it is expected, but when we generate the code, we generate - // the alternate kind of code. - // - public override Expression DoResolve (EmitContext ec) - { - type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod); - is_ref = (mod & Parameter.Modifier.ISBYREF) != 0; - is_out = (mod & Parameter.Modifier.OUT) != 0; - eclass = ExprClass.Variable; - - if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc)) - return null; - - return this; - } - - override public Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod); - is_ref = (mod & Parameter.Modifier.ISBYREF) != 0; - is_out = (mod & Parameter.Modifier.OUT) != 0; - eclass = ExprClass.Variable; - - if (is_out && ec.DoFlowAnalysis) - ec.SetParameterAssigned (idx); - - return this; - } - - static void EmitLdArg (ILGenerator ig, int x) - { - if (x <= 255){ - switch (x){ - case 0: ig.Emit (OpCodes.Ldarg_0); break; - case 1: ig.Emit (OpCodes.Ldarg_1); break; - case 2: ig.Emit (OpCodes.Ldarg_2); break; - case 3: ig.Emit (OpCodes.Ldarg_3); break; - default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break; - } - } else - ig.Emit (OpCodes.Ldarg, x); - } - - // - // This method is used by parameters that are references, that are - // being passed as references: we only want to pass the pointer (that - // is already stored in the parameter, not the address of the pointer, - // and not the value of the variable). - // - public void EmitLoad (EmitContext ec) - { - ILGenerator ig = ec.ig; - int arg_idx = idx; - - if (!ec.IsStatic) - arg_idx++; - - EmitLdArg (ig, arg_idx); - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - int arg_idx = idx; - - if (!ec.IsStatic) - arg_idx++; - - EmitLdArg (ig, arg_idx); - - if (!is_ref) - return; - - // - // If we are a reference, we loaded on the stack a pointer - // Now lets load the real value - // - LoadFromPtr (ig, type); - } - - public void EmitAssign (EmitContext ec, Expression source) - { - ILGenerator ig = ec.ig; - int arg_idx = idx; - - if (!ec.IsStatic) - arg_idx++; - - if (is_ref) - EmitLdArg (ig, arg_idx); - - source.Emit (ec); - - if (is_ref) - StoreFromPtr (ig, type); - else { - if (arg_idx <= 255) - ig.Emit (OpCodes.Starg_S, (byte) arg_idx); - else - ig.Emit (OpCodes.Starg, arg_idx); - } - } - - public void AddressOf (EmitContext ec, AddressOp mode) - { - int arg_idx = idx; - - if (!ec.IsStatic) - arg_idx++; - - if (is_ref){ - if (arg_idx <= 255) - ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx); - else - ec.ig.Emit (OpCodes.Ldarg, arg_idx); - } else { - if (arg_idx <= 255) - ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx); - else - ec.ig.Emit (OpCodes.Ldarga, arg_idx); - } - } - - } - - /// <summary> - /// Used for arguments to New(), Invocation() - /// </summary> - public class Argument { - public enum AType : byte { - Expression, - Ref, - Out - }; - - public readonly AType ArgType; - public Expression Expr; - - public Argument (Expression expr, AType type) - { - this.Expr = expr; - this.ArgType = type; - } - - public Type Type { - get { - if (ArgType == AType.Ref || ArgType == AType.Out) - return TypeManager.LookupType (Expr.Type.ToString () + "&"); - else - return Expr.Type; - } - } - - public Parameter.Modifier GetParameterModifier () - { - switch (ArgType) { - case AType.Out: - return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; - - case AType.Ref: - return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; - - default: - return Parameter.Modifier.NONE; - } - } - - public static string FullDesc (Argument a) - { - return (a.ArgType == AType.Ref ? "ref " : - (a.ArgType == AType.Out ? "out " : "")) + - TypeManager.CSharpName (a.Expr.Type); - } - - public bool ResolveMethodGroup (EmitContext ec, Location loc) - { - // FIXME: csc doesn't report any error if you try to use `ref' or - // `out' in a delegate creation expression. - Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); - if (Expr == null) - return false; - - return true; - } - - public bool Resolve (EmitContext ec, Location loc) - { - if (ArgType == AType.Ref) { - Expr = Expr.Resolve (ec); - if (Expr == null) - return false; - - Expr = Expr.ResolveLValue (ec, Expr); - } else if (ArgType == AType.Out) - Expr = Expr.ResolveLValue (ec, new EmptyExpression ()); - else - Expr = Expr.Resolve (ec); - - if (Expr == null) - return false; - - if (ArgType == AType.Expression) - return true; - - if (Expr.eclass != ExprClass.Variable){ - // - // We just probe to match the CSC output - // - if (Expr.eclass == ExprClass.PropertyAccess || - Expr.eclass == ExprClass.IndexerAccess){ - Report.Error ( - 206, loc, - "A property or indexer can not be passed as an out or ref " + - "parameter"); - } else { - Report.Error ( - 1510, loc, - "An lvalue is required as an argument to out or ref"); - } - return false; - } - - return true; - } - - public void Emit (EmitContext ec) - { - // - // Ref and Out parameters need to have their addresses taken. - // - // ParameterReferences might already be references, so we want - // to pass just the value - // - if (ArgType == AType.Ref || ArgType == AType.Out){ - AddressOp mode = AddressOp.Store; - - if (ArgType == AType.Ref) - mode |= AddressOp.Load; - - if (Expr is ParameterReference){ - ParameterReference pr = (ParameterReference) Expr; - - if (pr.is_ref) - pr.EmitLoad (ec); - else { - - pr.AddressOf (ec, mode); - } - } else - ((IMemoryLocation)Expr).AddressOf (ec, mode); - } else - Expr.Emit (ec); - } - } - - /// <summary> - /// Invocation of methods or delegates. - /// </summary> - public class Invocation : ExpressionStatement { - public readonly ArrayList Arguments; - - Expression expr; - MethodBase method = null; - bool is_base; - - static Hashtable method_parameter_cache; - - static Invocation () - { - method_parameter_cache = new PtrHashtable (); - } - - // - // arguments is an ArrayList, but we do not want to typecast, - // as it might be null. - // - // FIXME: only allow expr to be a method invocation or a - // delegate invocation (7.5.5) - // - public Invocation (Expression expr, ArrayList arguments, Location l) - { - this.expr = expr; - Arguments = arguments; - loc = l; - } - - public Expression Expr { - get { - return expr; - } - } - - /// <summary> - /// Returns the Parameters (a ParameterData interface) for the - /// Method `mb' - /// </summary> - public static ParameterData GetParameterData (MethodBase mb) - { - object pd = method_parameter_cache [mb]; - object ip; - - if (pd != null) - return (ParameterData) pd; - - - ip = TypeManager.LookupParametersByBuilder (mb); - if (ip != null){ - method_parameter_cache [mb] = ip; - - return (ParameterData) ip; - } else { - ParameterInfo [] pi = mb.GetParameters (); - ReflectionParameters rp = new ReflectionParameters (pi); - method_parameter_cache [mb] = rp; - - return (ParameterData) rp; - } - } - - /// <summary> - /// Determines "better conversion" as specified in 7.4.2.3 - /// Returns : 1 if a->p is better - /// 0 if a->q or neither is better - /// </summary> - static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc) - { - Type argument_type = a.Type; - Expression argument_expr = a.Expr; - - if (argument_type == null) - throw new Exception ("Expression of type " + a.Expr + " does not resolve its type"); - - // - // This is a special case since csc behaves this way. I can't find - // it anywhere in the spec but oh well ... - // - if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type) - return 1; - else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type) - return 0; - - if (p == q) - return 0; - - if (argument_type == p) - return 1; - - if (argument_type == q) - return 0; - - // - // Now probe whether an implicit constant expression conversion - // can be used. - // - // An implicit constant expression conversion permits the following - // conversions: - // - // * A constant-expression of type `int' can be converted to type - // sbyte, byute, short, ushort, uint, ulong provided the value of - // of the expression is withing the range of the destination type. - // - // * A constant-expression of type long can be converted to type - // ulong, provided the value of the constant expression is not negative - // - // FIXME: Note that this assumes that constant folding has - // taken place. We dont do constant folding yet. - // - - if (argument_expr is IntConstant){ - IntConstant ei = (IntConstant) argument_expr; - int value = ei.Value; - - if (p == TypeManager.sbyte_type){ - if (value >= SByte.MinValue && value <= SByte.MaxValue) - return 1; - } else if (p == TypeManager.byte_type){ - if (q == TypeManager.sbyte_type && - value >= SByte.MinValue && value <= SByte.MaxValue) - return 0; - else if (Byte.MinValue >= 0 && value <= Byte.MaxValue) - return 1; - } else if (p == TypeManager.short_type){ - if (value >= Int16.MinValue && value <= Int16.MaxValue) - return 1; - } else if (p == TypeManager.ushort_type){ - if (q == TypeManager.short_type && - value >= Int16.MinValue && value <= Int16.MaxValue) - return 0; - else if (value >= UInt16.MinValue && value <= UInt16.MaxValue) - return 1; - } else if (p == TypeManager.int32_type){ - if (value >= Int32.MinValue && value <= Int32.MaxValue) - return 1; - } else if (p == TypeManager.uint32_type){ - // - // we can optimize this case: a positive int32 - // always fits on a uint32 - // - if (value >= 0) - return 1; - } else if (p == TypeManager.uint64_type){ - // - // we can optimize this case: a positive int32 - // always fits on a uint64 - // - if (q == TypeManager.int64_type) - return 0; - else if (value >= 0) - return 1; - } else if (p == TypeManager.int64_type){ - return 1; - } - } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){ - LongConstant lc = (LongConstant) argument_expr; - - if (p == TypeManager.uint64_type){ - if (lc.Value > 0) - return 1; - } - } - - if (q == null) { - Expression tmp = ConvertImplicit (ec, argument_expr, p, loc); - - if (tmp != null) - return 1; - else - return 0; - } - - Expression p_tmp = new EmptyExpression (p); - Expression q_tmp = new EmptyExpression (q); - - if (ImplicitConversionExists (ec, p_tmp, q) == true && - ImplicitConversionExists (ec, q_tmp, p) == false) - return 1; - - if (p == TypeManager.sbyte_type) - if (q == TypeManager.byte_type || q == TypeManager.ushort_type || - q == TypeManager.uint32_type || q == TypeManager.uint64_type) - return 1; - - if (p == TypeManager.short_type) - if (q == TypeManager.ushort_type || q == TypeManager.uint32_type || - q == TypeManager.uint64_type) - return 1; - - if (p == TypeManager.int32_type) - if (q == TypeManager.uint32_type || q == TypeManager.uint64_type) - return 1; - - if (p == TypeManager.int64_type) - if (q == TypeManager.uint64_type) - return 1; - - return 0; - } - - /// <summary> - /// Determines "Better function" - /// </summary> - /// <remarks> - /// and returns an integer indicating : - /// 0 if candidate ain't better - /// 1 if candidate is better than the current best match - /// </remarks> - static int BetterFunction (EmitContext ec, ArrayList args, - MethodBase candidate, MethodBase best, - bool expanded_form, Location loc) - { - ParameterData candidate_pd = GetParameterData (candidate); - ParameterData best_pd; - int argument_count; - - if (args == null) - argument_count = 0; - else - argument_count = args.Count; - - int cand_count = candidate_pd.Count; - - if (cand_count == 0 && argument_count == 0) - return 1; - - if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) - if (cand_count != argument_count) - return 0; - - if (best == null) { - int x = 0; - - if (argument_count == 0 && cand_count == 1 && - candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS) - return 1; - - for (int j = argument_count; j > 0;) { - j--; - - Argument a = (Argument) args [j]; - Type t = candidate_pd.ParameterType (j); - - if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS) - if (expanded_form) - t = t.GetElementType (); - - x = BetterConversion (ec, a, t, null, loc); - - if (x <= 0) - break; - } - - if (x > 0) - return 1; - else - return 0; - } - - best_pd = GetParameterData (best); - - int rating1 = 0, rating2 = 0; - - for (int j = 0; j < argument_count; ++j) { - int x, y; - - Argument a = (Argument) args [j]; - - Type ct = candidate_pd.ParameterType (j); - Type bt = best_pd.ParameterType (j); - - if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS) - if (expanded_form) - ct = ct.GetElementType (); - - if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS) - if (expanded_form) - bt = bt.GetElementType (); - - x = BetterConversion (ec, a, ct, bt, loc); - y = BetterConversion (ec, a, bt, ct, loc); - - if (x < y) - return 0; - - rating1 += x; - rating2 += y; - } - - if (rating1 > rating2) - return 1; - else - return 0; - } - - public static string FullMethodDesc (MethodBase mb) - { - string ret_type = ""; - - if (mb is MethodInfo) - ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType); - - StringBuilder sb = new StringBuilder (ret_type); - sb.Append (" "); - sb.Append (mb.ReflectedType.ToString ()); - sb.Append ("."); - sb.Append (mb.Name); - - ParameterData pd = GetParameterData (mb); - - int count = pd.Count; - sb.Append (" ("); - - for (int i = count; i > 0; ) { - i--; - - sb.Append (pd.ParameterDesc (count - i - 1)); - if (i != 0) - sb.Append (", "); - } - - sb.Append (")"); - return sb.ToString (); - } - - public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc) - { - MemberInfo [] miset; - MethodGroupExpr union; - - if (mg1 == null){ - if (mg2 == null) - return null; - return (MethodGroupExpr) mg2; - } else { - if (mg2 == null) - return (MethodGroupExpr) mg1; - } - - MethodGroupExpr left_set = null, right_set = null; - int length1 = 0, length2 = 0; - - left_set = (MethodGroupExpr) mg1; - length1 = left_set.Methods.Length; - - right_set = (MethodGroupExpr) mg2; - length2 = right_set.Methods.Length; - - ArrayList common = new ArrayList (); - - foreach (MethodBase l in left_set.Methods){ - foreach (MethodBase r in right_set.Methods){ - if (l != r) - continue; - common.Add (r); - break; - } - } - - miset = new MemberInfo [length1 + length2 - common.Count]; - left_set.Methods.CopyTo (miset, 0); - - int k = length1; - - foreach (MemberInfo mi in right_set.Methods){ - if (!common.Contains (mi)) - miset [k++] = mi; - } - - union = new MethodGroupExpr (miset, loc); - - return union; - } - - /// <summary> - /// Determines is the candidate method, if a params method, is applicable - /// in its expanded form to the given set of arguments - /// </summary> - static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate) - { - int arg_count; - - if (arguments == null) - arg_count = 0; - else - arg_count = arguments.Count; - - ParameterData pd = GetParameterData (candidate); - - int pd_count = pd.Count; - - if (pd_count == 0) - return false; - - if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) - return false; - - if (pd_count - 1 > arg_count) - return false; - - if (pd_count == 1 && arg_count == 0) - return true; - - // - // If we have come this far, the case which remains is when the number of parameters - // is less than or equal to the argument count. - // - for (int i = 0; i < pd_count - 1; ++i) { - - Argument a = (Argument) arguments [i]; - - Parameter.Modifier a_mod = a.GetParameterModifier () & - ~(Parameter.Modifier.OUT | Parameter.Modifier.REF); - Parameter.Modifier p_mod = pd.ParameterModifier (i) & - ~(Parameter.Modifier.OUT | Parameter.Modifier.REF); - - if (a_mod == p_mod) { - - if (a_mod == Parameter.Modifier.NONE) - if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i))) - return false; - - if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { - Type pt = pd.ParameterType (i); - - if (!pt.IsByRef) - pt = TypeManager.LookupType (pt.FullName + "&"); - - if (pt != a.Type) - return false; - } - } else - return false; - - } - - Type element_type = pd.ParameterType (pd_count - 1).GetElementType (); - - for (int i = pd_count - 1; i < arg_count; i++) { - Argument a = (Argument) arguments [i]; - - if (!StandardConversionExists (a.Expr, element_type)) - return false; - } - - return true; - } - - /// <summary> - /// Determines if the candidate method is applicable (section 14.4.2.1) - /// to the given set of arguments - /// </summary> - static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate) - { - int arg_count; - - if (arguments == null) - arg_count = 0; - else - arg_count = arguments.Count; - - ParameterData pd = GetParameterData (candidate); - - int pd_count = pd.Count; - - if (arg_count != pd.Count) - return false; - - for (int i = arg_count; i > 0; ) { - i--; - - Argument a = (Argument) arguments [i]; - - Parameter.Modifier a_mod = a.GetParameterModifier () & - ~(Parameter.Modifier.OUT | Parameter.Modifier.REF); - Parameter.Modifier p_mod = pd.ParameterModifier (i) & - ~(Parameter.Modifier.OUT | Parameter.Modifier.REF); - - if (a_mod == p_mod || - (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) { - if (a_mod == Parameter.Modifier.NONE) - if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i))) - return false; - - if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { - Type pt = pd.ParameterType (i); - - if (!pt.IsByRef) - pt = TypeManager.LookupType (pt.FullName + "&"); - - if (pt != a.Type) - return false; - } - } else - return false; - } - - return true; - } - - - - /// <summary> - /// Find the Applicable Function Members (7.4.2.1) - /// - /// me: Method Group expression with the members to select. - /// it might contain constructors or methods (or anything - /// that maps to a method). - /// - /// Arguments: ArrayList containing resolved Argument objects. - /// - /// loc: The location if we want an error to be reported, or a Null - /// location for "probing" purposes. - /// - /// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo) - /// that is the best match of me on Arguments. - /// - /// </summary> - public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me, - ArrayList Arguments, Location loc) - { - ArrayList afm = new ArrayList (); - MethodBase method = null; - Type current_type = null; - int argument_count; - ArrayList candidates = new ArrayList (); - - - foreach (MethodBase candidate in me.Methods){ - int x; - - // If we're going one level higher in the class hierarchy, abort if - // we already found an applicable method. - if (candidate.DeclaringType != current_type) { - current_type = candidate.DeclaringType; - if (method != null) - break; - } - - // Check if candidate is applicable (section 14.4.2.1) - if (!IsApplicable (ec, Arguments, candidate)) - continue; - - candidates.Add (candidate); - x = BetterFunction (ec, Arguments, candidate, method, false, loc); - - if (x == 0) - continue; - - method = candidate; - } - - if (Arguments == null) - argument_count = 0; - else - argument_count = Arguments.Count; - - // - // Now we see if we can find params functions, applicable in their expanded form - // since if they were applicable in their normal form, they would have been selected - // above anyways - // - bool chose_params_expanded = false; - - if (method == null) { - candidates = new ArrayList (); - foreach (MethodBase candidate in me.Methods){ - if (!IsParamsMethodApplicable (ec, Arguments, candidate)) - continue; - - candidates.Add (candidate); - - int x = BetterFunction (ec, Arguments, candidate, method, true, loc); - if (x == 0) - continue; - - method = candidate; - chose_params_expanded = true; - } - } - - if (method == null) { - // - // Okay so we have failed to find anything so we - // return by providing info about the closest match - // - for (int i = 0; i < me.Methods.Length; ++i) { - - MethodBase c = (MethodBase) me.Methods [i]; - ParameterData pd = GetParameterData (c); - - if (pd.Count != argument_count) - continue; - - VerifyArgumentsCompat (ec, Arguments, argument_count, c, false, - null, loc); - } - - return null; - } - - // - // Now check that there are no ambiguities i.e the selected method - // should be better than all the others - // - - foreach (MethodBase candidate in candidates){ - if (candidate == method) - continue; - - // - // If a normal method is applicable in the sense that it has the same - // number of arguments, then the expanded params method is never applicable - // so we debar the params method. - // - if (IsParamsMethodApplicable (ec, Arguments, candidate) && - IsApplicable (ec, Arguments, method)) - continue; - - int x = BetterFunction (ec, Arguments, method, candidate, - chose_params_expanded, loc); - - if (x != 1) { - Report.Error ( - 121, loc, - "Ambiguous call when selecting function due to implicit casts"); - return null; - } - } - - // - // And now check if the arguments are all compatible, perform conversions - // if necessary etc. and return if everything is all right - // - - if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method, - chose_params_expanded, null, loc)) - return null; - - return method; - } - - public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments, - int argument_count, - MethodBase method, - bool chose_params_expanded, - Type delegate_type, - Location loc) - { - ParameterData pd = GetParameterData (method); - int pd_count = pd.Count; - - for (int j = 0; j < argument_count; j++) { - Argument a = (Argument) Arguments [j]; - Expression a_expr = a.Expr; - Type parameter_type = pd.ParameterType (j); - - if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS && - chose_params_expanded) - parameter_type = TypeManager.TypeToCoreType (parameter_type.GetElementType ()); - - if (a.Type != parameter_type){ - Expression conv; - - conv = ConvertImplicit (ec, a_expr, parameter_type, loc); - - if (conv == null) { - if (!Location.IsNull (loc)) { - if (delegate_type == null) - Report.Error (1502, loc, - "The best overloaded match for method '" + - FullMethodDesc (method) + - "' has some invalid arguments"); - else - Report.Error (1594, loc, - "Delegate '" + delegate_type.ToString () + - "' has some invalid arguments."); - Report.Error (1503, loc, - "Argument " + (j+1) + - ": Cannot convert from '" + Argument.FullDesc (a) - + "' to '" + pd.ParameterDesc (j) + "'"); - } - - return false; - } - - // - // Update the argument with the implicit conversion - // - if (a_expr != conv) - a.Expr = conv; - } - - Parameter.Modifier a_mod = a.GetParameterModifier () & - ~(Parameter.Modifier.OUT | Parameter.Modifier.REF); - Parameter.Modifier p_mod = pd.ParameterModifier (j) & - ~(Parameter.Modifier.OUT | Parameter.Modifier.REF); - - - if (a_mod != p_mod && - pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) { - if (!Location.IsNull (loc)) { - Console.WriteLine ("A:P: " + a.GetParameterModifier ()); - Console.WriteLine ("PP:: " + pd.ParameterModifier (j)); - Console.WriteLine ("PT: " + parameter_type.IsByRef); - Report.Error (1502, loc, - "The best overloaded match for method '" + FullMethodDesc (method)+ - "' has some invalid arguments"); - Report.Error (1503, loc, - "Argument " + (j+1) + - ": Cannot convert from '" + Argument.FullDesc (a) - + "' to '" + pd.ParameterDesc (j) + "'"); - } - - return false; - } - } - - return true; - } - - public override Expression DoResolve (EmitContext ec) - { - // - // First, resolve the expression that is used to - // trigger the invocation - // - if (expr is BaseAccess) - is_base = true; - - expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); - if (expr == null) - return null; - - if (!(expr is MethodGroupExpr)) { - Type expr_type = expr.Type; - - if (expr_type != null){ - bool IsDelegate = TypeManager.IsDelegateType (expr_type); - if (IsDelegate) - return (new DelegateInvocation ( - this.expr, Arguments, loc)).Resolve (ec); - } - } - - if (!(expr is MethodGroupExpr)){ - expr.Error118 (ResolveFlags.MethodGroup); - return null; - } - - // - // Next, evaluate all the expressions in the argument list - // - if (Arguments != null){ - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return null; - } - } - - MethodGroupExpr mg = (MethodGroupExpr) expr; - method = OverloadResolve (ec, mg, Arguments, loc); - - if (method == null){ - Error (-6, - "Could not find any applicable function for this argument list"); - return null; - } - - MethodInfo mi = method as MethodInfo; - if (mi != null) { - type = TypeManager.TypeToCoreType (mi.ReturnType); - if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) - SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name); - } - - if (type.IsPointer){ - if (!ec.InUnsafe){ - UnsafeError (loc); - return null; - } - } - - // - // Only base will allow this invocation to happen. - // - if (is_base && method.IsAbstract){ - Report.Error (205, loc, "Cannot call an abstract base member: " + - FullMethodDesc (method)); - return null; - } - - eclass = ExprClass.Value; - return this; - } - - // <summary> - // Emits the list of arguments as an array - // </summary> - static void EmitParams (EmitContext ec, int idx, ArrayList arguments) - { - ILGenerator ig = ec.ig; - int count = arguments.Count - idx; - Argument a = (Argument) arguments [idx]; - Type t = a.Expr.Type; - string array_type = t.FullName + "[]"; - LocalBuilder array; - - array = ig.DeclareLocal (TypeManager.LookupType (array_type)); - IntConstant.EmitInt (ig, count); - ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t)); - ig.Emit (OpCodes.Stloc, array); - - int top = arguments.Count; - for (int j = idx; j < top; j++){ - a = (Argument) arguments [j]; - - ig.Emit (OpCodes.Ldloc, array); - IntConstant.EmitInt (ig, j - idx); - - bool is_stobj; - OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj); - if (is_stobj) - ig.Emit (OpCodes.Ldelema, t); - - a.Emit (ec); - - if (is_stobj) - ig.Emit (OpCodes.Stobj, t); - else - ig.Emit (op); - } - ig.Emit (OpCodes.Ldloc, array); - } - - /// <summary> - /// Emits a list of resolved Arguments that are in the arguments - /// ArrayList. - /// - /// The MethodBase argument might be null if the - /// emission of the arguments is known not to contain - /// a `params' field (for example in constructors or other routines - /// that keep their arguments in this structure) - /// </summary> - public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments) - { - ParameterData pd; - if (mb != null) - pd = GetParameterData (mb); - else - pd = null; - - // - // If we are calling a params method with no arguments, special case it - // - if (arguments == null){ - if (pd != null && pd.Count > 0 && - pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){ - ILGenerator ig = ec.ig; - - IntConstant.EmitInt (ig, 0); - ig.Emit (OpCodes.Newarr, pd.ParameterType (0).GetElementType ()); - } - - return; - } - - int top = arguments.Count; - - for (int i = 0; i < top; i++){ - Argument a = (Argument) arguments [i]; - - if (pd != null){ - if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){ - // - // Special case if we are passing the same data as the - // params argument, do not put it in an array. - // - if (pd.ParameterType (i) == a.Type) - a.Emit (ec); - else - EmitParams (ec, i, arguments); - return; - } - } - - a.Emit (ec); - } - - if (pd != null && pd.Count > top && - pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){ - ILGenerator ig = ec.ig; - - IntConstant.EmitInt (ig, 0); - ig.Emit (OpCodes.Newarr, pd.ParameterType (top).GetElementType ()); - } - } - - /// <remarks> - /// is_base tells whether we want to force the use of the `call' - /// opcode instead of using callvirt. Call is required to call - /// a specific method, while callvirt will always use the most - /// recent method in the vtable. - /// - /// is_static tells whether this is an invocation on a static method - /// - /// instance_expr is an expression that represents the instance - /// it must be non-null if is_static is false. - /// - /// method is the method to invoke. - /// - /// Arguments is the list of arguments to pass to the method or constructor. - /// </remarks> - public static void EmitCall (EmitContext ec, bool is_base, - bool is_static, Expression instance_expr, - MethodBase method, ArrayList Arguments, Location loc) - { - ILGenerator ig = ec.ig; - bool struct_call = false; - - Type decl_type = method.DeclaringType; - - if (!RootContext.StdLib) { - // Replace any calls to the system's System.Array type with calls to - // the newly created one. - if (method == TypeManager.system_int_array_get_length) - method = TypeManager.int_array_get_length; - else if (method == TypeManager.system_int_array_get_rank) - method = TypeManager.int_array_get_rank; - else if (method == TypeManager.system_object_array_clone) - method = TypeManager.object_array_clone; - else if (method == TypeManager.system_int_array_get_length_int) - method = TypeManager.int_array_get_length_int; - else if (method == TypeManager.system_int_array_get_lower_bound_int) - method = TypeManager.int_array_get_lower_bound_int; - else if (method == TypeManager.system_int_array_get_upper_bound_int) - method = TypeManager.int_array_get_upper_bound_int; - else if (method == TypeManager.system_void_array_copyto_array_int) - method = TypeManager.void_array_copyto_array_int; - } - - // - // This checks the `ConditionalAttribute' on the method, and the - // ObsoleteAttribute - // - TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc); - if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0) - return; - if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0) - return; - - if (!is_static){ - if (decl_type.IsValueType) - struct_call = true; - // - // If this is ourselves, push "this" - // - if (instance_expr == null){ - ig.Emit (OpCodes.Ldarg_0); - } else { - // - // Push the instance expression - // - if (instance_expr.Type.IsValueType){ - // - // Special case: calls to a function declared in a - // reference-type with a value-type argument need - // to have their value boxed. - - struct_call = true; - if (decl_type.IsValueType){ - // - // If the expression implements IMemoryLocation, then - // we can optimize and use AddressOf on the - // return. - // - // If not we have to use some temporary storage for - // it. - if (instance_expr is IMemoryLocation){ - ((IMemoryLocation)instance_expr). - AddressOf (ec, AddressOp.LoadStore); - } - else { - Type t = instance_expr.Type; - - instance_expr.Emit (ec); - LocalBuilder temp = ig.DeclareLocal (t); - ig.Emit (OpCodes.Stloc, temp); - ig.Emit (OpCodes.Ldloca, temp); - } - } else { - instance_expr.Emit (ec); - ig.Emit (OpCodes.Box, instance_expr.Type); - } - } else - instance_expr.Emit (ec); - } - } - - EmitArguments (ec, method, Arguments); - - if (is_static || struct_call || is_base){ - if (method is MethodInfo) { - ig.Emit (OpCodes.Call, (MethodInfo) method); - } else - ig.Emit (OpCodes.Call, (ConstructorInfo) method); - } else { - if (method is MethodInfo) - ig.Emit (OpCodes.Callvirt, (MethodInfo) method); - else - ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method); - } - } - - public override void Emit (EmitContext ec) - { - MethodGroupExpr mg = (MethodGroupExpr) this.expr; - - EmitCall ( - ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc); - } - - public override void EmitStatement (EmitContext ec) - { - Emit (ec); - - // - // Pop the return value if there is one - // - if (method is MethodInfo){ - Type ret = ((MethodInfo)method).ReturnType; - if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type) - ec.ig.Emit (OpCodes.Pop); - } - } - } - - // - // This class is used to "disable" the code generation for the - // temporary variable when initializing value types. - // - class EmptyAddressOf : EmptyExpression, IMemoryLocation { - public void AddressOf (EmitContext ec, AddressOp Mode) - { - // nothing - } - } - - /// <summary> - /// Implements the new expression - /// </summary> - public class New : ExpressionStatement { - public readonly ArrayList Arguments; - public readonly Expression RequestedType; - - MethodBase method = null; - - // - // If set, the new expression is for a value_target, and - // we will not leave anything on the stack. - // - Expression value_target; - bool value_target_set = false; - - public New (Expression requested_type, ArrayList arguments, Location l) - { - RequestedType = requested_type; - Arguments = arguments; - loc = l; - } - - public Expression ValueTypeVariable { - get { - return value_target; - } - - set { - value_target = value; - value_target_set = true; - } - } - - // - // This function is used to disable the following code sequence for - // value type initialization: - // - // AddressOf (temporary) - // Construct/Init - // LoadTemporary - // - // Instead the provide will have provided us with the address on the - // stack to store the results. - // - static Expression MyEmptyExpression; - - public void DisableTemporaryValueType () - { - if (MyEmptyExpression == null) - MyEmptyExpression = new EmptyAddressOf (); - - // - // To enable this, look into: - // test-34 and test-89 and self bootstrapping. - // - // For instance, we can avoid a copy by using `newobj' - // instead of Call + Push-temp on value types. -// value_target = MyEmptyExpression; - } - - public override Expression DoResolve (EmitContext ec) - { - type = ec.DeclSpace.ResolveType (RequestedType, false, loc); - - if (type == null) - return null; - - bool IsDelegate = TypeManager.IsDelegateType (type); - - if (IsDelegate) - return (new NewDelegate (type, Arguments, loc)).Resolve (ec); - - if (type.IsInterface || type.IsAbstract){ - Error ( - 144, "It is not possible to create instances of interfaces " + - "or abstract classes"); - return null; - } - - bool is_struct = false; - is_struct = type.IsValueType; - eclass = ExprClass.Value; - - // - // SRE returns a match for .ctor () on structs (the object constructor), - // so we have to manually ignore it. - // - if (is_struct && Arguments == null) - return this; - - Expression ml; - ml = MemberLookupFinal (ec, null, type, ".ctor", - MemberTypes.Constructor, - AllBindingFlags | BindingFlags.DeclaredOnly, loc); - - if (ml == null) - return null; - - if (! (ml is MethodGroupExpr)){ - if (!is_struct){ - ml.Error118 ("method group"); - return null; - } - } - - if (ml != null) { - if (Arguments != null){ - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return null; - } - } - - method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, - Arguments, loc); - - } - - if (method == null) { - if (!is_struct || Arguments.Count > 0) { - Error (1501, - "New invocation: Can not find a constructor for " + - "this argument list"); - return null; - } - } - return this; - } - - // - // This DoEmit can be invoked in two contexts: - // * As a mechanism that will leave a value on the stack (new object) - // * As one that wont (init struct) - // - // You can control whether a value is required on the stack by passing - // need_value_on_stack. The code *might* leave a value on the stack - // so it must be popped manually - // - // If we are dealing with a ValueType, we have a few - // situations to deal with: - // - // * The target is a ValueType, and we have been provided - // the instance (this is easy, we are being assigned). - // - // * The target of New is being passed as an argument, - // to a boxing operation or a function that takes a - // ValueType. - // - // In this case, we need to create a temporary variable - // that is the argument of New. - // - // Returns whether a value is left on the stack - // - bool DoEmit (EmitContext ec, bool need_value_on_stack) - { - bool is_value_type = type.IsValueType; - ILGenerator ig = ec.ig; - - if (is_value_type){ - IMemoryLocation ml; - - // Allow DoEmit() to be called multiple times. - // We need to create a new LocalTemporary each time since - // you can't share LocalBuilders among ILGeneators. - if (!value_target_set) - value_target = new LocalTemporary (ec, type); - - ml = (IMemoryLocation) value_target; - ml.AddressOf (ec, AddressOp.Store); - } - - if (method != null) - Invocation.EmitArguments (ec, method, Arguments); - - if (is_value_type){ - if (method == null) - ig.Emit (OpCodes.Initobj, type); - else - ig.Emit (OpCodes.Call, (ConstructorInfo) method); - if (need_value_on_stack){ - value_target.Emit (ec); - return true; - } - return false; - } else { - ig.Emit (OpCodes.Newobj, (ConstructorInfo) method); - return true; - } - } - - public override void Emit (EmitContext ec) - { - DoEmit (ec, true); - } - - public override void EmitStatement (EmitContext ec) - { - if (DoEmit (ec, false)) - ec.ig.Emit (OpCodes.Pop); - } - } - - /// <summary> - /// 14.5.10.2: Represents an array creation expression. - /// </summary> - /// - /// <remarks> - /// There are two possible scenarios here: one is an array creation - /// expression that specifies the dimensions and optionally the - /// initialization data and the other which does not need dimensions - /// specified but where initialization data is mandatory. - /// </remarks> - public class ArrayCreation : ExpressionStatement { - Expression requested_base_type; - ArrayList initializers; - - // - // The list of Argument types. - // This is used to construct the `newarray' or constructor signature - // - ArrayList arguments; - - // - // Method used to create the array object. - // - MethodBase new_method = null; - - Type array_element_type; - Type underlying_type; - bool is_one_dimensional = false; - bool is_builtin_type = false; - bool expect_initializers = false; - int num_arguments = 0; - int dimensions = 0; - string rank; - - ArrayList array_data; - - Hashtable bounds; - - // - // The number of array initializers that we can handle - // via the InitializeArray method - through EmitStaticInitializers - // - int num_automatic_initializers; - - const int max_automatic_initializers = 6; - - public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l) - { - this.requested_base_type = requested_base_type; - this.initializers = initializers; - this.rank = rank; - loc = l; - - arguments = new ArrayList (); - - foreach (Expression e in exprs) { - arguments.Add (new Argument (e, Argument.AType.Expression)); - num_arguments++; - } - } - - public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l) - { - this.requested_base_type = requested_base_type; - this.initializers = initializers; - this.rank = rank; - loc = l; - - //this.rank = rank.Substring (0, rank.LastIndexOf ("[")); - // - //string tmp = rank.Substring (rank.LastIndexOf ("[")); - // - //dimensions = tmp.Length - 1; - expect_initializers = true; - } - - public Expression FormArrayType (Expression base_type, int idx_count, string rank) - { - StringBuilder sb = new StringBuilder (rank); - - sb.Append ("["); - for (int i = 1; i < idx_count; i++) - sb.Append (","); - - sb.Append ("]"); - - return new ComposedCast (base_type, sb.ToString (), loc); - } - - void Error_IncorrectArrayInitializer () - { - Error (178, "Incorrectly structured array initializer"); - } - - public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims) - { - if (specified_dims) { - Argument a = (Argument) arguments [idx]; - - if (!a.Resolve (ec, loc)) - return false; - - if (!(a.Expr is Constant)) { - Error (150, "A constant value is expected"); - return false; - } - - int value = (int) ((Constant) a.Expr).GetValue (); - - if (value != probe.Count) { - Error_IncorrectArrayInitializer (); - return false; - } - - bounds [idx] = value; - } - - int child_bounds = -1; - foreach (object o in probe) { - if (o is ArrayList) { - int current_bounds = ((ArrayList) o).Count; - - if (child_bounds == -1) - child_bounds = current_bounds; - - else if (child_bounds != current_bounds){ - Error_IncorrectArrayInitializer (); - return false; - } - bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims); - if (!ret) - return false; - } else { - if (child_bounds != -1){ - Error_IncorrectArrayInitializer (); - return false; - } - - Expression tmp = (Expression) o; - tmp = tmp.Resolve (ec); - if (tmp == null) - continue; - - // Console.WriteLine ("I got: " + tmp); - // Handle initialization from vars, fields etc. - - Expression conv = ConvertImplicitRequired ( - ec, tmp, underlying_type, loc); - - if (conv == null) - return false; - - if (conv is StringConstant) - array_data.Add (conv); - else if (conv is Constant) { - array_data.Add (conv); - num_automatic_initializers++; - } else - array_data.Add (conv); - } - } - - return true; - } - - public void UpdateIndices (EmitContext ec) - { - int i = 0; - for (ArrayList probe = initializers; probe != null;) { - if (probe.Count > 0 && probe [0] is ArrayList) { - Expression e = new IntConstant (probe.Count); - arguments.Add (new Argument (e, Argument.AType.Expression)); - - bounds [i++] = probe.Count; - - probe = (ArrayList) probe [0]; - - } else { - Expression e = new IntConstant (probe.Count); - arguments.Add (new Argument (e, Argument.AType.Expression)); - - bounds [i++] = probe.Count; - probe = null; - } - } - - } - - public bool ValidateInitializers (EmitContext ec, Type array_type) - { - if (initializers == null) { - if (expect_initializers) - return false; - else - return true; - } - - if (underlying_type == null) - return false; - - // - // We use this to store all the date values in the order in which we - // will need to store them in the byte blob later - // - array_data = new ArrayList (); - bounds = new Hashtable (); - - bool ret; - - if (arguments != null) { - ret = CheckIndices (ec, initializers, 0, true); - return ret; - } else { - arguments = new ArrayList (); - - ret = CheckIndices (ec, initializers, 0, false); - - if (!ret) - return false; - - UpdateIndices (ec); - - if (arguments.Count != dimensions) { - Error_IncorrectArrayInitializer (); - return false; - } - - return ret; - } - } - - void Error_NegativeArrayIndex () - { - Error (284, "Can not create array with a negative size"); - } - - // - // Converts `source' to an int, uint, long or ulong. - // - Expression ExpressionToArrayArgument (EmitContext ec, Expression source) - { - Expression target; - - bool old_checked = ec.CheckState; - ec.CheckState = true; - - target = ConvertImplicit (ec, source, TypeManager.int32_type, loc); - if (target == null){ - target = ConvertImplicit (ec, source, TypeManager.uint32_type, loc); - if (target == null){ - target = ConvertImplicit (ec, source, TypeManager.int64_type, loc); - if (target == null){ - target = ConvertImplicit (ec, source, TypeManager.uint64_type, loc); - if (target == null) - Expression.Error_CannotConvertImplicit (loc, source.Type, TypeManager.int32_type); - } - } - } - ec.CheckState = old_checked; - - // - // Only positive constants are allowed at compile time - // - if (target is Constant){ - if (target is IntConstant){ - if (((IntConstant) target).Value < 0){ - Error_NegativeArrayIndex (); - return null; - } - } - - if (target is LongConstant){ - if (((LongConstant) target).Value < 0){ - Error_NegativeArrayIndex (); - return null; - } - } - - } - - return target; - } - - // - // Creates the type of the array - // - bool LookupType (EmitContext ec) - { - StringBuilder array_qualifier = new StringBuilder (rank); - - // - // `In the first form allocates an array instace of the type that results - // from deleting each of the individual expression from the expression list' - // - if (num_arguments > 0) { - array_qualifier.Append ("["); - for (int i = num_arguments-1; i > 0; i--) - array_qualifier.Append (","); - array_qualifier.Append ("]"); - } - - // - // Lookup the type - // - Expression array_type_expr; - array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc); - type = ec.DeclSpace.ResolveType (array_type_expr, false, loc); - - if (type == null) - return false; - - underlying_type = type; - if (underlying_type.IsArray) - underlying_type = TypeManager.TypeToCoreType (underlying_type.GetElementType ()); - dimensions = type.GetArrayRank (); - - return true; - } - - public override Expression DoResolve (EmitContext ec) - { - int arg_count; - - if (!LookupType (ec)) - return null; - - // - // First step is to validate the initializers and fill - // in any missing bits - // - if (!ValidateInitializers (ec, type)) - return null; - - if (arguments == null) - arg_count = 0; - else { - arg_count = arguments.Count; - foreach (Argument a in arguments){ - if (!a.Resolve (ec, loc)) - return null; - - Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc); - if (real_arg == null) - return null; - - a.Expr = real_arg; - } - } - - array_element_type = TypeManager.TypeToCoreType (type.GetElementType ()); - - if (arg_count == 1) { - is_one_dimensional = true; - eclass = ExprClass.Value; - return this; - } - - is_builtin_type = TypeManager.IsBuiltinType (type); - - if (is_builtin_type) { - Expression ml; - - ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, - AllBindingFlags, loc); - - if (!(ml is MethodGroupExpr)) { - ml.Error118 ("method group"); - return null; - } - - if (ml == null) { - Error (-6, "New invocation: Can not find a constructor for " + - "this argument list"); - return null; - } - - new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc); - - if (new_method == null) { - Error (-6, "New invocation: Can not find a constructor for " + - "this argument list"); - return null; - } - - eclass = ExprClass.Value; - return this; - } else { - ModuleBuilder mb = CodeGen.ModuleBuilder; - ArrayList args = new ArrayList (); - - if (arguments != null) { - for (int i = 0; i < arg_count; i++) - args.Add (TypeManager.int32_type); - } - - Type [] arg_types = null; - - if (args.Count > 0) - arg_types = new Type [args.Count]; - - args.CopyTo (arg_types, 0); - - new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null, - arg_types); - - if (new_method == null) { - Error (-6, "New invocation: Can not find a constructor for " + - "this argument list"); - return null; - } - - eclass = ExprClass.Value; - return this; - } - } - - public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc) - { - int factor; - byte [] data; - byte [] element; - int count = array_data.Count; - - if (underlying_type.IsEnum) - underlying_type = TypeManager.EnumToUnderlying (underlying_type); - - factor = GetTypeSize (underlying_type); - if (factor == 0) - throw new Exception ("unrecognized type in MakeByteBlob: " + underlying_type); - - data = new byte [(count * factor + 4) & ~3]; - int idx = 0; - - for (int i = 0; i < count; ++i) { - object v = array_data [i]; - - if (v is EnumConstant) - v = ((EnumConstant) v).Child; - - if (v is Constant && !(v is StringConstant)) - v = ((Constant) v).GetValue (); - else { - idx += factor; - continue; - } - - if (underlying_type == TypeManager.int64_type){ - if (!(v is Expression)){ - long val = (long) v; - - for (int j = 0; j < factor; ++j) { - data [idx + j] = (byte) (val & 0xFF); - val = (val >> 8); - } - } - } else if (underlying_type == TypeManager.uint64_type){ - if (!(v is Expression)){ - ulong val = (ulong) v; - - for (int j = 0; j < factor; ++j) { - data [idx + j] = (byte) (val & 0xFF); - val = (val >> 8); - } - } - } else if (underlying_type == TypeManager.float_type) { - if (!(v is Expression)){ - element = BitConverter.GetBytes ((float) v); - - for (int j = 0; j < factor; ++j) - data [idx + j] = element [j]; - } - } else if (underlying_type == TypeManager.double_type) { - if (!(v is Expression)){ - element = BitConverter.GetBytes ((double) v); - - for (int j = 0; j < factor; ++j) - data [idx + j] = element [j]; - } - } else if (underlying_type == TypeManager.char_type){ - if (!(v is Expression)){ - int val = (int) ((char) v); - - data [idx] = (byte) (val & 0xff); - data [idx+1] = (byte) (val >> 8); - } - } else if (underlying_type == TypeManager.short_type){ - if (!(v is Expression)){ - int val = (int) ((short) v); - - data [idx] = (byte) (val & 0xff); - data [idx+1] = (byte) (val >> 8); - } - } else if (underlying_type == TypeManager.ushort_type){ - if (!(v is Expression)){ - int val = (int) ((ushort) v); - - data [idx] = (byte) (val & 0xff); - data [idx+1] = (byte) (val >> 8); - } - } else if (underlying_type == TypeManager.int32_type) { - if (!(v is Expression)){ - int val = (int) v; - - data [idx] = (byte) (val & 0xff); - data [idx+1] = (byte) ((val >> 8) & 0xff); - data [idx+2] = (byte) ((val >> 16) & 0xff); - data [idx+3] = (byte) (val >> 24); - } - } else if (underlying_type == TypeManager.uint32_type) { - if (!(v is Expression)){ - uint val = (uint) v; - - data [idx] = (byte) (val & 0xff); - data [idx+1] = (byte) ((val >> 8) & 0xff); - data [idx+2] = (byte) ((val >> 16) & 0xff); - data [idx+3] = (byte) (val >> 24); - } - } else if (underlying_type == TypeManager.sbyte_type) { - if (!(v is Expression)){ - sbyte val = (sbyte) v; - data [idx] = (byte) val; - } - } else if (underlying_type == TypeManager.byte_type) { - if (!(v is Expression)){ - byte val = (byte) v; - data [idx] = (byte) val; - } - } else if (underlying_type == TypeManager.bool_type) { - if (!(v is Expression)){ - bool val = (bool) v; - data [idx] = (byte) (val ? 1 : 0); - } - } else if (underlying_type == TypeManager.decimal_type){ - if (!(v is Expression)){ - int [] bits = Decimal.GetBits ((decimal) v); - int p = idx; - - for (int j = 0; j < 4; j++){ - data [p++] = (byte) (bits [j] & 0xff); - data [p++] = (byte) ((bits [j] >> 8) & 0xff); - data [p++] = (byte) ((bits [j] >> 16) & 0xff); - data [p++] = (byte) (bits [j] >> 24); - } - } - } else - throw new Exception ("Unrecognized type in MakeByteBlob: " + underlying_type); - - idx += factor; - } - - return data; - } - - // - // Emits the initializers for the array - // - void EmitStaticInitializers (EmitContext ec, bool is_expression) - { - // - // First, the static data - // - FieldBuilder fb; - ILGenerator ig = ec.ig; - - byte [] data = MakeByteBlob (array_data, underlying_type, loc); - - fb = RootContext.MakeStaticData (data); - - if (is_expression) - ig.Emit (OpCodes.Dup); - ig.Emit (OpCodes.Ldtoken, fb); - ig.Emit (OpCodes.Call, - TypeManager.void_initializearray_array_fieldhandle); - } - - // - // Emits pieces of the array that can not be computed at compile - // time (variables and string locations). - // - // This always expect the top value on the stack to be the array - // - void EmitDynamicInitializers (EmitContext ec, bool is_expression) - { - ILGenerator ig = ec.ig; - int dims = bounds.Count; - int [] current_pos = new int [dims]; - int top = array_data.Count; - LocalBuilder temp = ig.DeclareLocal (type); - - ig.Emit (OpCodes.Stloc, temp); - - MethodInfo set = null; - - if (dims != 1){ - Type [] args; - ModuleBuilder mb = null; - mb = CodeGen.ModuleBuilder; - args = new Type [dims + 1]; - - int j; - for (j = 0; j < dims; j++) - args [j] = TypeManager.int32_type; - - args [j] = array_element_type; - - set = mb.GetArrayMethod ( - type, "Set", - CallingConventions.HasThis | CallingConventions.Standard, - TypeManager.void_type, args); - } - - for (int i = 0; i < top; i++){ - - Expression e = null; - - if (array_data [i] is Expression) - e = (Expression) array_data [i]; - - if (e != null) { - // - // Basically we do this for string literals and - // other non-literal expressions - // - if (e is EnumConstant){ - e = ((EnumConstant) e).Child; - } - - if (e is StringConstant || !(e is Constant) || - num_automatic_initializers <= max_automatic_initializers) { - Type etype = e.Type; - - ig.Emit (OpCodes.Ldloc, temp); - - for (int idx = 0; idx < dims; idx++) - IntConstant.EmitInt (ig, current_pos [idx]); - - // - // If we are dealing with a struct, get the - // address of it, so we can store it. - // - if ((dims == 1) && - etype.IsSubclassOf (TypeManager.value_type) && - (!TypeManager.IsBuiltinType (etype) || - etype == TypeManager.decimal_type)) { - if (e is New){ - New n = (New) e; - - // - // Let new know that we are providing - // the address where to store the results - // - n.DisableTemporaryValueType (); - } - - ig.Emit (OpCodes.Ldelema, etype); - } - - e.Emit (ec); - - if (dims == 1) - ArrayAccess.EmitStoreOpcode (ig, array_element_type); - else - ig.Emit (OpCodes.Call, set); - } - } - - // - // Advance counter - // - for (int j = dims - 1; j >= 0; j--){ - current_pos [j]++; - if (current_pos [j] < (int) bounds [j]) - break; - current_pos [j] = 0; - } - } - - if (is_expression) - ig.Emit (OpCodes.Ldloc, temp); - } - - void EmitArrayArguments (EmitContext ec) - { - ILGenerator ig = ec.ig; - - foreach (Argument a in arguments) { - Type atype = a.Type; - a.Emit (ec); - - if (atype == TypeManager.uint64_type) - ig.Emit (OpCodes.Conv_Ovf_U4); - else if (atype == TypeManager.int64_type) - ig.Emit (OpCodes.Conv_Ovf_I4); - } - } - - void DoEmit (EmitContext ec, bool is_statement) - { - ILGenerator ig = ec.ig; - - EmitArrayArguments (ec); - if (is_one_dimensional) - ig.Emit (OpCodes.Newarr, array_element_type); - else { - if (is_builtin_type) - ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method); - else - ig.Emit (OpCodes.Newobj, (MethodInfo) new_method); - } - - if (initializers != null){ - // - // FIXME: Set this variable correctly. - // - bool dynamic_initializers = true; - - if (underlying_type != TypeManager.string_type && - underlying_type != TypeManager.object_type) { - if (num_automatic_initializers > max_automatic_initializers) - EmitStaticInitializers (ec, dynamic_initializers || !is_statement); - } - - if (dynamic_initializers) - EmitDynamicInitializers (ec, !is_statement); - } - } - - public override void Emit (EmitContext ec) - { - DoEmit (ec, false); - } - - public override void EmitStatement (EmitContext ec) - { - DoEmit (ec, true); - } - - } - - /// <summary> - /// Represents the `this' construct - /// </summary> - public class This : Expression, IAssignMethod, IMemoryLocation, IVariable { - - Block block; - VariableInfo vi; - - public This (Block block, Location loc) - { - this.loc = loc; - this.block = block; - } - - public This (Location loc) - { - this.loc = loc; - } - - public bool IsAssigned (EmitContext ec, Location loc) - { - if (vi == null) - return true; - - return vi.IsAssigned (ec, loc); - } - - public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc) - { - if (vi == null) - return true; - - return vi.IsFieldAssigned (ec, field_name, loc); - } - - public void SetAssigned (EmitContext ec) - { - if (vi != null) - vi.SetAssigned (ec); - } - - public void SetFieldAssigned (EmitContext ec, string field_name) - { - if (vi != null) - vi.SetFieldAssigned (ec, field_name); - } - - public override Expression DoResolve (EmitContext ec) - { - eclass = ExprClass.Variable; - type = ec.ContainerType; - - if (ec.IsStatic){ - Error (26, "Keyword this not valid in static code"); - return null; - } - - if (block != null) - vi = block.ThisVariable; - - return this; - } - - override public Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - DoResolve (ec); - - VariableInfo vi = ec.CurrentBlock.ThisVariable; - if (vi != null) - vi.SetAssigned (ec); - - if (ec.TypeContainer is Class){ - Error (1604, "Cannot assign to `this'"); - return null; - } - - return this; - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - ig.Emit (OpCodes.Ldarg_0); - if (ec.TypeContainer is Struct) - ig.Emit (OpCodes.Ldobj, type); - } - - public void EmitAssign (EmitContext ec, Expression source) - { - ILGenerator ig = ec.ig; - - if (ec.TypeContainer is Struct){ - ig.Emit (OpCodes.Ldarg_0); - source.Emit (ec); - ig.Emit (OpCodes.Stobj, type); - } else { - source.Emit (ec); - ig.Emit (OpCodes.Starg, 0); - } - } - - public void AddressOf (EmitContext ec, AddressOp mode) - { - ec.ig.Emit (OpCodes.Ldarg_0); - - // FIMXE - // FIGURE OUT WHY LDARG_S does not work - // - // consider: struct X { int val; int P { set { val = value; }}} - // - // Yes, this looks very bad. Look at `NOTAS' for - // an explanation. - // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0); - } - } - - /// <summary> - /// Implements the typeof operator - /// </summary> - public class TypeOf : Expression { - public readonly Expression QueriedType; - Type typearg; - - public TypeOf (Expression queried_type, Location l) - { - QueriedType = queried_type; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc); - - if (typearg == null) - return null; - - type = TypeManager.type_type; - eclass = ExprClass.Type; - return this; - } - - public override void Emit (EmitContext ec) - { - ec.ig.Emit (OpCodes.Ldtoken, typearg); - ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); - } - - public Type TypeArg { - get { return typearg; } - } - } - - /// <summary> - /// Implements the sizeof expression - /// </summary> - public class SizeOf : Expression { - public readonly Expression QueriedType; - Type type_queried; - - public SizeOf (Expression queried_type, Location l) - { - this.QueriedType = queried_type; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - if (!ec.InUnsafe) { - Error (233, "Sizeof may only be used in an unsafe context " + - "(consider using System.Runtime.InteropServices.Marshal.Sizeof"); - return null; - } - - type_queried = ec.DeclSpace.ResolveType (QueriedType, false, loc); - if (type_queried == null) - return null; - - if (!TypeManager.IsUnmanagedType (type_queried)){ - Report.Error (208, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")"); - return null; - } - - type = TypeManager.int32_type; - eclass = ExprClass.Value; - return this; - } - - public override void Emit (EmitContext ec) - { - int size = GetTypeSize (type_queried); - - if (size == 0) - ec.ig.Emit (OpCodes.Sizeof, type_queried); - else - IntConstant.EmitInt (ec.ig, size); - } - } - - /// <summary> - /// Implements the member access expression - /// </summary> - public class MemberAccess : Expression, ITypeExpression { - public readonly string Identifier; - Expression expr; - Expression member_lookup; - - public MemberAccess (Expression expr, string id, Location l) - { - this.expr = expr; - Identifier = id; - loc = l; - } - - public Expression Expr { - get { - return expr; - } - } - - static void error176 (Location loc, string name) - { - Report.Error (176, loc, "Static member `" + - name + "' cannot be accessed " + - "with an instance reference, qualify with a " + - "type name instead"); - } - - static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc) - { - if (left_original == null) - return false; - - if (!(left_original is SimpleName)) - return false; - - SimpleName sn = (SimpleName) left_original; - - Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc); - if (t != null) - return true; - - return false; - } - - public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup, - Expression left, Location loc, - Expression left_original) - { - bool left_is_type, left_is_explicit; - - // If `left' is null, then we're called from SimpleNameResolve and this is - // a member in the currently defining class. - if (left == null) { - left_is_type = ec.IsStatic || ec.IsFieldInitializer; - left_is_explicit = false; - - // Implicitly default to `this' unless we're static. - if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext) - left = ec.This; - } else { - left_is_type = left is TypeExpr; - left_is_explicit = true; - } - - if (member_lookup is FieldExpr){ - FieldExpr fe = (FieldExpr) member_lookup; - FieldInfo fi = fe.FieldInfo; - Type decl_type = fi.DeclaringType; - - if (fi is FieldBuilder) { - Const c = TypeManager.LookupConstant ((FieldBuilder) fi); - - if (c != null) { - object o = c.LookupConstantValue (ec); - object real_value = ((Constant) c.Expr).GetValue (); - - return Constantify (real_value, fi.FieldType); - } - } - - if (fi.IsLiteral) { - Type t = fi.FieldType; - - object o; - - if (fi is FieldBuilder) - o = TypeManager.GetValue ((FieldBuilder) fi); - else - o = fi.GetValue (fi); - - if (decl_type.IsSubclassOf (TypeManager.enum_type)) { - if (left_is_explicit && !left_is_type && - !IdenticalNameAndTypeName (ec, left_original, loc)) { - error176 (loc, fe.FieldInfo.Name); - return null; - } - - Expression enum_member = MemberLookup ( - ec, decl_type, "value__", MemberTypes.Field, - AllBindingFlags, loc); - - Enum en = TypeManager.LookupEnum (decl_type); - - Constant c; - if (en != null) - c = Constantify (o, en.UnderlyingType); - else - c = Constantify (o, enum_member.Type); - - return new EnumConstant (c, decl_type); - } - - Expression exp = Constantify (o, t); - - if (left_is_explicit && !left_is_type) { - error176 (loc, fe.FieldInfo.Name); - return null; - } - - return exp; - } - - if (fi.FieldType.IsPointer && !ec.InUnsafe){ - UnsafeError (loc); - return null; - } - } - - if (member_lookup is EventExpr) { - - EventExpr ee = (EventExpr) member_lookup; - - // - // If the event is local to this class, we transform ourselves into - // a FieldExpr - // - - if (ee.EventInfo.DeclaringType == ec.ContainerType) { - MemberInfo mi = GetFieldFromEvent (ee); - - if (mi == null) { - // - // If this happens, then we have an event with its own - // accessors and private field etc so there's no need - // to transform ourselves : we should instead flag an error - // - Assign.error70 (ee.EventInfo, loc); - return null; - } - - Expression ml = ExprClassFromMemberInfo (ec, mi, loc); - - if (ml == null) { - Report.Error (-200, loc, "Internal error!!"); - return null; - } - - return ResolveMemberAccess (ec, ml, left, loc, left_original); - } - } - - if (member_lookup is IMemberExpr) { - IMemberExpr me = (IMemberExpr) member_lookup; - - if (left_is_type){ - MethodGroupExpr mg = me as MethodGroupExpr; - if ((mg != null) && left_is_explicit && left.Type.IsInterface) - mg.IsExplicitImpl = left_is_explicit; - - if (!me.IsStatic){ - if (IdenticalNameAndTypeName (ec, left_original, loc)) - return member_lookup; - - SimpleName.Error_ObjectRefRequired (ec, loc, me.Name); - return null; - } - - } else { - if (!me.IsInstance){ - if (IdenticalNameAndTypeName (ec, left_original, loc)) - return member_lookup; - - if (left_is_explicit) { - error176 (loc, me.Name); - return null; - } - } - - // - // Since we can not check for instance objects in SimpleName, - // becaue of the rule that allows types and variables to share - // the name (as long as they can be de-ambiguated later, see - // IdenticalNameAndTypeName), we have to check whether left - // is an instance variable in a static context - // - // However, if the left-hand value is explicitly given, then - // it is already our instance expression, so we aren't in - // static context. - // - - if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){ - IMemberExpr mexp = (IMemberExpr) left; - - if (!mexp.IsStatic){ - SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name); - return null; - } - } - - me.InstanceExpression = left; - } - - return member_lookup; - } - - if (member_lookup is TypeExpr){ - member_lookup.Resolve (ec, ResolveFlags.Type); - return member_lookup; - } - - Console.WriteLine ("Left is: " + left); - Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet"); - Environment.Exit (0); - return null; - } - - public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags) - { - if (type != null) - throw new Exception (); - // - // Resolve the expression with flow analysis turned off, we'll do the definite - // assignment checks later. This is because we don't know yet what the expression - // will resolve to - it may resolve to a FieldExpr and in this case we must do the - // definite assignment check on the actual field and not on the whole struct. - // - - Expression original = expr; - expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis); - - if (expr == null) - return null; - - if (expr is SimpleName){ - SimpleName child_expr = (SimpleName) expr; - - Expression new_expr = new SimpleName (child_expr.Name, Identifier, loc); - - return new_expr.Resolve (ec, flags); - } - - // - // TODO: I mailed Ravi about this, and apparently we can get rid - // of this and put it in the right place. - // - // Handle enums here when they are in transit. - // Note that we cannot afford to hit MemberLookup in this case because - // it will fail to find any members at all - // - - int errors = Report.Errors; - - Type expr_type = expr.Type; - if ((expr is TypeExpr) && (expr_type.IsSubclassOf (TypeManager.enum_type))){ - - Enum en = TypeManager.LookupEnum (expr_type); - - if (en != null) { - object value = en.LookupEnumValue (ec, Identifier, loc); - - if (value != null){ - Constant c = Constantify (value, en.UnderlyingType); - return new EnumConstant (c, expr_type); - } - } - } - - if (expr_type.IsPointer){ - Error (23, "The `.' operator can not be applied to pointer operands (" + - TypeManager.CSharpName (expr_type) + ")"); - return null; - } - - member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc); - if (member_lookup == null) - return null; - - if (member_lookup is TypeExpr){ - member_lookup.Resolve (ec, ResolveFlags.Type); - return member_lookup; - } else if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) - return null; - - member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original); - if (member_lookup == null) - return null; - - // The following DoResolve/DoResolveLValue will do the definite assignment - // check. - - if (right_side != null) - member_lookup = member_lookup.DoResolveLValue (ec, right_side); - else - member_lookup = member_lookup.DoResolve (ec); - - return member_lookup; - } - - public override Expression DoResolve (EmitContext ec) - { - return DoResolve (ec, null, ResolveFlags.VariableOrValue | - ResolveFlags.SimpleName | ResolveFlags.Type); - } - - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - return DoResolve (ec, right_side, ResolveFlags.VariableOrValue | - ResolveFlags.SimpleName | ResolveFlags.Type); - } - - public Expression DoResolveType (EmitContext ec) - { - return DoResolve (ec, null, ResolveFlags.Type); - } - - public override void Emit (EmitContext ec) - { - throw new Exception ("Should not happen"); - } - - public override string ToString () - { - return expr + "." + Identifier; - } - } - - /// <summary> - /// Implements checked expressions - /// </summary> - public class CheckedExpr : Expression { - - public Expression Expr; - - public CheckedExpr (Expression e, Location l) - { - Expr = e; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - bool last_const_check = ec.ConstantCheckState; - - ec.ConstantCheckState = true; - Expr = Expr.Resolve (ec); - ec.ConstantCheckState = last_const_check; - - if (Expr == null) - return null; - - if (Expr is Constant) - return Expr; - - eclass = Expr.eclass; - type = Expr.Type; - return this; - } - - public override void Emit (EmitContext ec) - { - bool last_check = ec.CheckState; - bool last_const_check = ec.ConstantCheckState; - - ec.CheckState = true; - ec.ConstantCheckState = true; - Expr.Emit (ec); - ec.CheckState = last_check; - ec.ConstantCheckState = last_const_check; - } - - } - - /// <summary> - /// Implements the unchecked expression - /// </summary> - public class UnCheckedExpr : Expression { - - public Expression Expr; - - public UnCheckedExpr (Expression e, Location l) - { - Expr = e; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - bool last_const_check = ec.ConstantCheckState; - - ec.ConstantCheckState = false; - Expr = Expr.Resolve (ec); - ec.ConstantCheckState = last_const_check; - - if (Expr == null) - return null; - - if (Expr is Constant) - return Expr; - - eclass = Expr.eclass; - type = Expr.Type; - return this; - } - - public override void Emit (EmitContext ec) - { - bool last_check = ec.CheckState; - bool last_const_check = ec.ConstantCheckState; - - ec.CheckState = false; - ec.ConstantCheckState = false; - Expr.Emit (ec); - ec.CheckState = last_check; - ec.ConstantCheckState = last_const_check; - } - - } - - /// <summary> - /// An Element Access expression. - /// - /// During semantic analysis these are transformed into - /// IndexerAccess or ArrayAccess - /// </summary> - public class ElementAccess : Expression { - public ArrayList Arguments; - public Expression Expr; - - public ElementAccess (Expression e, ArrayList e_list, Location l) - { - Expr = e; - - loc = l; - - if (e_list == null) - return; - - Arguments = new ArrayList (); - foreach (Expression tmp in e_list) - Arguments.Add (new Argument (tmp, Argument.AType.Expression)); - - } - - bool CommonResolve (EmitContext ec) - { - Expr = Expr.Resolve (ec); - - if (Expr == null) - return false; - - if (Arguments == null) - return false; - - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return false; - } - - return true; - } - - Expression MakePointerAccess () - { - Type t = Expr.Type; - - if (t == TypeManager.void_ptr_type){ - Error ( - 242, - "The array index operation is not valid for void pointers"); - return null; - } - if (Arguments.Count != 1){ - Error ( - 196, - "A pointer must be indexed by a single value"); - return null; - } - Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, - t, loc); - return new Indirection (p, loc); - } - - public override Expression DoResolve (EmitContext ec) - { - if (!CommonResolve (ec)) - return null; - - // - // We perform some simple tests, and then to "split" the emit and store - // code we create an instance of a different class, and return that. - // - // I am experimenting with this pattern. - // - Type t = Expr.Type; - - if (t.IsArray) - return (new ArrayAccess (this, loc)).Resolve (ec); - else if (t.IsPointer) - return MakePointerAccess (); - else - return (new IndexerAccess (this, loc)).Resolve (ec); - } - - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - if (!CommonResolve (ec)) - return null; - - Type t = Expr.Type; - if (t.IsArray) - return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side); - else if (t.IsPointer) - return MakePointerAccess (); - else - return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side); - } - - public override void Emit (EmitContext ec) - { - throw new Exception ("Should never be reached"); - } - } - - /// <summary> - /// Implements array access - /// </summary> - public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation { - // - // Points to our "data" repository - // - ElementAccess ea; - - LocalTemporary [] cached_locations; - - public ArrayAccess (ElementAccess ea_data, Location l) - { - ea = ea_data; - eclass = ExprClass.Variable; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - ExprClass eclass = ea.Expr.eclass; - -#if false - // As long as the type is valid - if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess || - eclass == ExprClass.Value)) { - ea.Expr.Error118 ("variable or value"); - return null; - } -#endif - - Type t = ea.Expr.Type; - if (t.GetArrayRank () != ea.Arguments.Count){ - ea.Error (22, - "Incorrect number of indexes for array " + - " expected: " + t.GetArrayRank () + " got: " + - ea.Arguments.Count); - return null; - } - type = TypeManager.TypeToCoreType (t.GetElementType ()); - if (type.IsPointer && !ec.InUnsafe){ - UnsafeError (ea.Location); - return null; - } - - foreach (Argument a in ea.Arguments){ - Type argtype = a.Type; - - if (argtype == TypeManager.int32_type || - argtype == TypeManager.uint32_type || - argtype == TypeManager.int64_type || - argtype == TypeManager.uint64_type) - continue; - - // - // Mhm. This is strage, because the Argument.Type is not the same as - // Argument.Expr.Type: the value changes depending on the ref/out setting. - // - // Wonder if I will run into trouble for this. - // - a.Expr = ExpressionToArrayArgument (ec, a.Expr, ea.Location); - if (a.Expr == null) - return null; - } - - eclass = ExprClass.Variable; - - return this; - } - - /// <summary> - /// Emits the right opcode to load an object of Type `t' - /// from an array of T - /// </summary> - static public void EmitLoadOpcode (ILGenerator ig, Type type) - { - if (type == TypeManager.byte_type || type == TypeManager.bool_type) - ig.Emit (OpCodes.Ldelem_U1); - else if (type == TypeManager.sbyte_type) - ig.Emit (OpCodes.Ldelem_I1); - else if (type == TypeManager.short_type) - ig.Emit (OpCodes.Ldelem_I2); - else if (type == TypeManager.ushort_type || type == TypeManager.char_type) - ig.Emit (OpCodes.Ldelem_U2); - else if (type == TypeManager.int32_type) - ig.Emit (OpCodes.Ldelem_I4); - else if (type == TypeManager.uint32_type) - ig.Emit (OpCodes.Ldelem_U4); - else if (type == TypeManager.uint64_type) - ig.Emit (OpCodes.Ldelem_I8); - else if (type == TypeManager.int64_type) - ig.Emit (OpCodes.Ldelem_I8); - else if (type == TypeManager.float_type) - ig.Emit (OpCodes.Ldelem_R4); - else if (type == TypeManager.double_type) - ig.Emit (OpCodes.Ldelem_R8); - else if (type == TypeManager.intptr_type) - ig.Emit (OpCodes.Ldelem_I); - else if (type.IsValueType){ - ig.Emit (OpCodes.Ldelema, type); - ig.Emit (OpCodes.Ldobj, type); - } else - ig.Emit (OpCodes.Ldelem_Ref); - } - - /// <summary> - /// Emits the right opcode to store an object of Type `t' - /// from an array of T. - /// </summary> - static public void EmitStoreOpcode (ILGenerator ig, Type t) - { - bool is_stobj; - OpCode op = GetStoreOpcode (t, out is_stobj); - if (is_stobj) - ig.Emit (OpCodes.Stobj, t); - else - ig.Emit (op); - } - - /// <summary> - /// Returns the right opcode to store an object of Type `t' - /// from an array of T. - /// </summary> - static public OpCode GetStoreOpcode (Type t, out bool is_stobj) - { - is_stobj = false; - t = TypeManager.TypeToCoreType (t); - if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type) - t = TypeManager.EnumToUnderlying (t); - if (t == TypeManager.byte_type || t == TypeManager.sbyte_type || - t == TypeManager.bool_type) - return OpCodes.Stelem_I1; - else if (t == TypeManager.short_type || t == TypeManager.ushort_type || - t == TypeManager.char_type) - return OpCodes.Stelem_I2; - else if (t == TypeManager.int32_type || t == TypeManager.uint32_type) - return OpCodes.Stelem_I4; - else if (t == TypeManager.int64_type || t == TypeManager.uint64_type) - return OpCodes.Stelem_I8; - else if (t == TypeManager.float_type) - return OpCodes.Stelem_R4; - else if (t == TypeManager.double_type) - return OpCodes.Stelem_R8; - else if (t == TypeManager.intptr_type) - return OpCodes.Stelem_I; - else if (t.IsValueType) { - is_stobj = true; - return OpCodes.Stobj; - } else - return OpCodes.Stelem_Ref; - } - - MethodInfo FetchGetMethod () - { - ModuleBuilder mb = CodeGen.ModuleBuilder; - int arg_count = ea.Arguments.Count; - Type [] args = new Type [arg_count]; - MethodInfo get; - - for (int i = 0; i < arg_count; i++){ - //args [i++] = a.Type; - args [i] = TypeManager.int32_type; - } - - get = mb.GetArrayMethod ( - ea.Expr.Type, "Get", - CallingConventions.HasThis | - CallingConventions.Standard, - type, args); - return get; - } - - - MethodInfo FetchAddressMethod () - { - ModuleBuilder mb = CodeGen.ModuleBuilder; - int arg_count = ea.Arguments.Count; - Type [] args = new Type [arg_count]; - MethodInfo address; - string ptr_type_name; - Type ret_type; - - ptr_type_name = type.FullName + "&"; - ret_type = Type.GetType (ptr_type_name); - - // - // It is a type defined by the source code we are compiling - // - if (ret_type == null){ - ret_type = mb.GetType (ptr_type_name); - } - - for (int i = 0; i < arg_count; i++){ - //args [i++] = a.Type; - args [i] = TypeManager.int32_type; - } - - address = mb.GetArrayMethod ( - ea.Expr.Type, "Address", - CallingConventions.HasThis | - CallingConventions.Standard, - ret_type, args); - - return address; - } - - // - // Load the array arguments into the stack. - // - // If we have been requested to cache the values (cached_locations array - // initialized), then load the arguments the first time and store them - // in locals. otherwise load from local variables. - // - void LoadArrayAndArguments (EmitContext ec) - { - ILGenerator ig = ec.ig; - - if (cached_locations == null){ - ea.Expr.Emit (ec); - foreach (Argument a in ea.Arguments){ - Type argtype = a.Expr.Type; - - a.Expr.Emit (ec); - - if (argtype == TypeManager.int64_type) - ig.Emit (OpCodes.Conv_Ovf_I); - else if (argtype == TypeManager.uint64_type) - ig.Emit (OpCodes.Conv_Ovf_I_Un); - } - return; - } - - if (cached_locations [0] == null){ - cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type); - ea.Expr.Emit (ec); - ig.Emit (OpCodes.Dup); - cached_locations [0].Store (ec); - - int j = 1; - - foreach (Argument a in ea.Arguments){ - Type argtype = a.Expr.Type; - - cached_locations [j] = new LocalTemporary (ec, TypeManager.intptr_type /* a.Expr.Type */); - a.Expr.Emit (ec); - if (argtype == TypeManager.int64_type) - ig.Emit (OpCodes.Conv_Ovf_I); - else if (argtype == TypeManager.uint64_type) - ig.Emit (OpCodes.Conv_Ovf_I_Un); - - ig.Emit (OpCodes.Dup); - cached_locations [j].Store (ec); - j++; - } - return; - } - - foreach (LocalTemporary lt in cached_locations) - lt.Emit (ec); - } - - public new void CacheTemporaries (EmitContext ec) - { - cached_locations = new LocalTemporary [ea.Arguments.Count + 1]; - } - - public override void Emit (EmitContext ec) - { - int rank = ea.Expr.Type.GetArrayRank (); - ILGenerator ig = ec.ig; - - LoadArrayAndArguments (ec); - - if (rank == 1) - EmitLoadOpcode (ig, type); - else { - MethodInfo method; - - method = FetchGetMethod (); - ig.Emit (OpCodes.Call, method); - } - } - - public void EmitAssign (EmitContext ec, Expression source) - { - int rank = ea.Expr.Type.GetArrayRank (); - ILGenerator ig = ec.ig; - Type t = source.Type; - - LoadArrayAndArguments (ec); - - // - // The stobj opcode used by value types will need - // an address on the stack, not really an array/array - // pair - // - if (rank == 1){ - if (t == TypeManager.enum_type || t == TypeManager.decimal_type || - (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t))) - ig.Emit (OpCodes.Ldelema, t); - } - - source.Emit (ec); - - if (rank == 1) - EmitStoreOpcode (ig, t); - else { - ModuleBuilder mb = CodeGen.ModuleBuilder; - int arg_count = ea.Arguments.Count; - Type [] args = new Type [arg_count + 1]; - MethodInfo set; - - for (int i = 0; i < arg_count; i++){ - //args [i++] = a.Type; - args [i] = TypeManager.int32_type; - } - - args [arg_count] = type; - - set = mb.GetArrayMethod ( - ea.Expr.Type, "Set", - CallingConventions.HasThis | - CallingConventions.Standard, - TypeManager.void_type, args); - - ig.Emit (OpCodes.Call, set); - } - } - - public void AddressOf (EmitContext ec, AddressOp mode) - { - int rank = ea.Expr.Type.GetArrayRank (); - ILGenerator ig = ec.ig; - - LoadArrayAndArguments (ec); - - if (rank == 1){ - ig.Emit (OpCodes.Ldelema, type); - } else { - MethodInfo address = FetchAddressMethod (); - ig.Emit (OpCodes.Call, address); - } - } - } - - - class Indexers { - public ArrayList getters, setters; - static Hashtable map; - - static Indexers () - { - map = new Hashtable (); - } - - Indexers (MemberInfo [] mi) - { - foreach (PropertyInfo property in mi){ - MethodInfo get, set; - - get = property.GetGetMethod (true); - if (get != null){ - if (getters == null) - getters = new ArrayList (); - - getters.Add (get); - } - - set = property.GetSetMethod (true); - if (set != null){ - if (setters == null) - setters = new ArrayList (); - setters.Add (set); - } - } - } - - static private Indexers GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type) - { - Indexers ix = (Indexers) map [lookup_type]; - - if (ix != null) - return ix; - - string p_name = TypeManager.IndexerPropertyName (lookup_type); - - MemberInfo [] mi = TypeManager.MemberLookup ( - caller_type, caller_type, lookup_type, MemberTypes.Property, - BindingFlags.Public | BindingFlags.Instance | - BindingFlags.DeclaredOnly, p_name); - - if (mi == null || mi.Length == 0) - return null; - - ix = new Indexers (mi); - map [lookup_type] = ix; - - return ix; - } - - static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) - { - Indexers ix = (Indexers) map [lookup_type]; - - if (ix != null) - return ix; - - ix = GetIndexersForTypeOrInterface (caller_type, lookup_type); - if (ix != null) - return ix; - - Type [] ifaces = TypeManager.GetInterfaces (lookup_type); - if (ifaces != null) { - foreach (Type itype in ifaces) { - ix = GetIndexersForTypeOrInterface (caller_type, itype); - if (ix != null) - return ix; - } - } - - return null; - } - } - - /// <summary> - /// Expressions that represent an indexer call. - /// </summary> - public class IndexerAccess : Expression, IAssignMethod { - // - // Points to our "data" repository - // - MethodInfo get, set; - Indexers ilist; - ArrayList set_arguments; - bool is_base_indexer; - - protected Type indexer_type; - protected Type current_type; - protected Expression instance_expr; - protected ArrayList arguments; - - public IndexerAccess (ElementAccess ea, Location loc) - : this (ea.Expr, false, loc) - { - this.arguments = ea.Arguments; - } - - protected IndexerAccess (Expression instance_expr, bool is_base_indexer, - Location loc) - { - this.instance_expr = instance_expr; - this.is_base_indexer = is_base_indexer; - this.eclass = ExprClass.Value; - this.loc = loc; - } - - protected virtual bool CommonResolve (EmitContext ec) - { - indexer_type = instance_expr.Type; - current_type = ec.ContainerType; - - return true; - } - - public override Expression DoResolve (EmitContext ec) - { - if (!CommonResolve (ec)) - return null; - - // - // Step 1: Query for all `Item' *properties*. Notice - // that the actual methods are pointed from here. - // - // This is a group of properties, piles of them. - - bool found_any = false, found_any_getters = false; - Type lookup_type = indexer_type; - while (lookup_type != null) { - ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc); - - if (ilist == null) { - lookup_type = lookup_type.BaseType; - continue; - } - - found_any = true; - - // - // Step 2: find the proper match - // - if (ilist.getters != null && ilist.getters.Count > 0) { - found_any_getters = true; - get = (MethodInfo) Invocation.OverloadResolve ( - ec, new MethodGroupExpr (ilist.getters, loc), arguments, loc); - - if (get != null) - break; - } - - lookup_type = lookup_type.BaseType; - } - - if (!found_any) { - Report.Error (21, loc, - "Type `" + TypeManager.CSharpName (indexer_type) + - "' does not have any indexers defined"); - return null; - } - - if (!found_any_getters) { - Error (154, "indexer can not be used in this context, because " + - "it lacks a `get' accessor"); - return null; - } - - if (get == null) { - Error (1501, "No Overload for method `this' takes `" + - arguments.Count + "' arguments"); - return null; - } - - // - // Only base will allow this invocation to happen. - // - if (get.IsAbstract && this is BaseIndexerAccess){ - Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (get)); - return null; - } - - type = get.ReturnType; - if (type.IsPointer && !ec.InUnsafe){ - UnsafeError (loc); - return null; - } - - eclass = ExprClass.IndexerAccess; - return this; - } - - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - if (!CommonResolve (ec)) - return null; - - Type right_type = right_side.Type; - - bool found_any = false, found_any_setters = false; - Type lookup_type = indexer_type; - while (lookup_type != null) { - ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc); - - if (ilist == null) { - lookup_type = lookup_type.BaseType; - continue; - } - - found_any = true; - - if (ilist.setters != null && ilist.setters.Count > 0) { - found_any_setters = true; - - set_arguments = (ArrayList) arguments.Clone (); - set_arguments.Add (new Argument (right_side, Argument.AType.Expression)); - set = (MethodInfo) Invocation.OverloadResolve ( - ec, new MethodGroupExpr (ilist.setters, loc), set_arguments, loc); - - if (set != null) - break; - } - - - lookup_type = lookup_type.BaseType; - } - - if (!found_any) { - Report.Error (21, loc, - "Type `" + TypeManager.CSharpName (indexer_type) + - "' does not have any indexers defined"); - return null; - } - - if (!found_any_setters) { - Error (154, "indexer can not be used in this context, because " + - "it lacks a `set' accessor"); - return null; - } - - if (set == null) { - Error (1501, "No Overload for method `this' takes `" + - arguments.Count + "' arguments"); - return null; - } - - // - // Only base will allow this invocation to happen. - // - if (set.IsAbstract && this is BaseIndexerAccess){ - Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (set)); - return null; - } - type = TypeManager.void_type; - eclass = ExprClass.IndexerAccess; - return this; - } - - public override void Emit (EmitContext ec) - { - Invocation.EmitCall (ec, false, false, instance_expr, get, arguments, loc); - } - - // - // source is ignored, because we already have a copy of it from the - // LValue resolution and we have already constructed a pre-cached - // version of the arguments (ea.set_arguments); - // - public void EmitAssign (EmitContext ec, Expression source) - { - Invocation.EmitCall (ec, false, false, instance_expr, set, set_arguments, loc); - } - } - - /// <summary> - /// The base operator for method names - /// </summary> - public class BaseAccess : Expression { - string member; - - public BaseAccess (string member, Location l) - { - this.member = member; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - Expression c = CommonResolve (ec); - - if (c == null) - return null; - - // - // MethodGroups use this opportunity to flag an error on lacking () - // - if (!(c is MethodGroupExpr)) - return c.Resolve (ec); - return c; - } - - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - Expression c = CommonResolve (ec); - - if (c == null) - return null; - - // - // MethodGroups use this opportunity to flag an error on lacking () - // - if (! (c is MethodGroupExpr)) - return c.DoResolveLValue (ec, right_side); - - return c; - } - - Expression CommonResolve (EmitContext ec) - { - Expression member_lookup; - Type current_type = ec.ContainerType; - Type base_type = current_type.BaseType; - Expression e; - - if (ec.IsStatic){ - Error (1511, "Keyword base is not allowed in static method"); - return null; - } - - member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member, - AllMemberTypes, AllBindingFlags, loc); - if (member_lookup == null) { - MemberLookupFailed (ec, base_type, base_type, member, null, loc); - return null; - } - - Expression left; - - if (ec.IsStatic) - left = new TypeExpr (base_type, loc); - else - left = ec.This; - - e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null); - - if (e is PropertyExpr){ - PropertyExpr pe = (PropertyExpr) e; - - pe.IsBase = true; - } - - return e; - } - - public override void Emit (EmitContext ec) - { - throw new Exception ("Should never be called"); - } - } - - /// <summary> - /// The base indexer operator - /// </summary> - public class BaseIndexerAccess : IndexerAccess { - public BaseIndexerAccess (ArrayList args, Location loc) - : base (null, true, loc) - { - arguments = new ArrayList (); - foreach (Expression tmp in args) - arguments.Add (new Argument (tmp, Argument.AType.Expression)); - } - - protected override bool CommonResolve (EmitContext ec) - { - instance_expr = ec.This; - - current_type = ec.ContainerType.BaseType; - indexer_type = current_type; - - foreach (Argument a in arguments){ - if (!a.Resolve (ec, loc)) - return false; - } - - return true; - } - } - - /// <summary> - /// This class exists solely to pass the Type around and to be a dummy - /// that can be passed to the conversion functions (this is used by - /// foreach implementation to typecast the object return value from - /// get_Current into the proper type. All code has been generated and - /// we only care about the side effect conversions to be performed - /// - /// This is also now used as a placeholder where a no-action expression - /// is needed (the `New' class). - /// </summary> - public class EmptyExpression : Expression { - public EmptyExpression () - { - type = TypeManager.object_type; - eclass = ExprClass.Value; - loc = Location.Null; - } - - public EmptyExpression (Type t) - { - type = t; - eclass = ExprClass.Value; - loc = Location.Null; - } - - public override Expression DoResolve (EmitContext ec) - { - return this; - } - - public override void Emit (EmitContext ec) - { - // nothing, as we only exist to not do anything. - } - - // - // This is just because we might want to reuse this bad boy - // instead of creating gazillions of EmptyExpressions. - // (CanConvertImplicit uses it) - // - public void SetType (Type t) - { - type = t; - } - } - - public class UserCast : Expression { - MethodBase method; - Expression source; - - public UserCast (MethodInfo method, Expression source, Location l) - { - this.method = method; - this.source = source; - type = method.ReturnType; - eclass = ExprClass.Value; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - // - // We are born fully resolved - // - return this; - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - source.Emit (ec); - - if (method is MethodInfo) - ig.Emit (OpCodes.Call, (MethodInfo) method); - else - ig.Emit (OpCodes.Call, (ConstructorInfo) method); - - } - } - - // <summary> - // This class is used to "construct" the type during a typecast - // operation. Since the Type.GetType class in .NET can parse - // the type specification, we just use this to construct the type - // one bit at a time. - // </summary> - public class ComposedCast : Expression, ITypeExpression { - Expression left; - string dim; - - public ComposedCast (Expression left, string dim, Location l) - { - this.left = left; - this.dim = dim; - loc = l; - } - - public Expression DoResolveType (EmitContext ec) - { - Type ltype = ec.DeclSpace.ResolveType (left, false, loc); - if (ltype == null) - return null; - - // - // ltype.Fullname is already fully qualified, so we can skip - // a lot of probes, and go directly to TypeManager.LookupType - // - string cname = ltype.FullName + dim; - type = TypeManager.LookupTypeDirect (cname); - if (type == null){ - // - // For arrays of enumerations we are having a problem - // with the direct lookup. Need to investigate. - // - // For now, fall back to the full lookup in that case. - // - type = RootContext.LookupType ( - ec.DeclSpace, cname, false, loc); - - if (type == null) - return null; - } - - if (!ec.ResolvingTypeTree){ - // - // If the above flag is set, this is being invoked from the ResolveType function. - // Upper layers take care of the type validity in this context. - // - if (!ec.InUnsafe && type.IsPointer){ - UnsafeError (loc); - return null; - } - } - - eclass = ExprClass.Type; - return this; - } - - public override Expression DoResolve (EmitContext ec) - { - return DoResolveType (ec); - } - - public override void Emit (EmitContext ec) - { - throw new Exception ("This should never be called"); - } - - public override string ToString () - { - return left + dim; - } - } - - // - // This class is used to represent the address of an array, used - // only by the Fixed statement, this is like the C "&a [0]" construct. - // - public class ArrayPtr : Expression { - Expression array; - - public ArrayPtr (Expression array, Location l) - { - Type array_type = array.Type.GetElementType (); - - this.array = array; - - string array_ptr_type_name = array_type.FullName + "*"; - - type = Type.GetType (array_ptr_type_name); - if (type == null){ - ModuleBuilder mb = CodeGen.ModuleBuilder; - - type = mb.GetType (array_ptr_type_name); - } - - eclass = ExprClass.Value; - loc = l; - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - array.Emit (ec); - IntLiteral.EmitInt (ig, 0); - ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ()); - } - - public override Expression DoResolve (EmitContext ec) - { - // - // We are born fully resolved - // - return this; - } - } - - // - // Used by the fixed statement - // - public class StringPtr : Expression { - LocalBuilder b; - - public StringPtr (LocalBuilder b, Location l) - { - this.b = b; - eclass = ExprClass.Value; - type = TypeManager.char_ptr_type; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - // This should never be invoked, we are born in fully - // initialized state. - - return this; - } - - public override void Emit (EmitContext ec) - { - ILGenerator ig = ec.ig; - - ig.Emit (OpCodes.Ldloc, b); - ig.Emit (OpCodes.Conv_I); - ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data); - ig.Emit (OpCodes.Add); - } - } - - // - // Implements the `stackalloc' keyword - // - public class StackAlloc : Expression { - Type otype; - Expression t; - Expression count; - - public StackAlloc (Expression type, Expression count, Location l) - { - t = type; - this.count = count; - loc = l; - } - - public override Expression DoResolve (EmitContext ec) - { - count = count.Resolve (ec); - if (count == null) - return null; - - if (count.Type != TypeManager.int32_type){ - count = ConvertImplicitRequired (ec, count, TypeManager.int32_type, loc); - if (count == null) - return null; - } - - if (ec.InCatch || ec.InFinally){ - Error (255, - "stackalloc can not be used in a catch or finally block"); - return null; - } - - otype = ec.DeclSpace.ResolveType (t, false, loc); - - if (otype == null) - return null; - - if (!TypeManager.VerifyUnManaged (otype, loc)) - return null; - - string ptr_name = otype.FullName + "*"; - type = Type.GetType (ptr_name); - if (type == null){ - ModuleBuilder mb = CodeGen.ModuleBuilder; - - type = mb.GetType (ptr_name); - } - eclass = ExprClass.Value; - - return this; - } - - public override void Emit (EmitContext ec) - { - int size = GetTypeSize (otype); - ILGenerator ig = ec.ig; - - if (size == 0) - ig.Emit (OpCodes.Sizeof, otype); - else - IntConstant.EmitInt (ig, size); - count.Emit (ec); - ig.Emit (OpCodes.Mul); - ig.Emit (OpCodes.Localloc); - } - } -} |