2 // ecore.cs: Core of the Expression representation for the intermediate tree.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001, 2002, 2003 Ximian, Inc.
11 namespace Mono
.CSharp
{
13 using System
.Collections
;
14 using System
.Diagnostics
;
15 using System
.Reflection
;
16 using System
.Reflection
.Emit
;
20 /// The ExprClass class contains the is used to pass the
21 /// classification of an expression (value, variable, namespace,
22 /// type, method group, property access, event access, indexer access,
25 public enum ExprClass
: byte {
40 /// This is used to tell Resolve in which types of expressions we're
44 public enum ResolveFlags
{
45 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
48 // Returns a type expression.
51 // Returns a method group.
54 // Allows SimpleNames to be returned.
55 // This is used by MemberAccess to construct long names that can not be
56 // partially resolved (namespace-qualified names for example).
59 // Mask of all the expression class flags.
62 // Disable control flow analysis while resolving the expression.
63 // This is used when resolving the instance expression of a field expression.
64 DisableFlowAnalysis
= 16,
66 // Set if this is resolving the first part of a MemberAccess.
71 // This is just as a hint to AddressOf of what will be done with the
74 public enum AddressOp
{
81 /// This interface is implemented by variables
83 public interface IMemoryLocation
{
85 /// The AddressOf method should generate code that loads
86 /// the address of the object and leaves it on the stack.
88 /// The `mode' argument is used to notify the expression
89 /// of whether this will be used to read from the address or
90 /// write to the address.
92 /// This is just a hint that can be used to provide good error
93 /// reporting, and should have no other side effects.
95 void AddressOf (EmitContext ec
, AddressOp mode
);
99 /// This interface is implemented by variables
101 public interface IVariable
{
102 VariableInfo VariableInfo
{
106 bool VerifyFixed (bool is_expression
);
110 /// This interface denotes an expression which evaluates to a member
111 /// of a struct or a class.
113 public interface IMemberExpr
116 /// The name of this member.
123 /// Whether this is an instance member.
130 /// Whether this is a static member.
137 /// The type which declares this member.
144 /// The instance expression associated with this member, if it's a
145 /// non-static member.
147 Expression InstanceExpression
{
153 /// Base class for expressions
155 public abstract class Expression
{
156 public ExprClass eclass
;
158 protected Location loc
;
170 public Location Location
{
177 /// Utility wrapper routine for Error, just to beautify the code
179 public void Error (int error
, string s
)
181 if (!Location
.IsNull (loc
))
182 Report
.Error (error
, loc
, s
);
184 Report
.Error (error
, s
);
188 /// Utility wrapper routine for Warning, just to beautify the code
190 public void Warning (int code
, string format
, params object[] args
)
192 Report
.Warning (code
, loc
, format
, args
);
196 /// Tests presence of ObsoleteAttribute and report proper error
198 protected void CheckObsoleteAttribute (Type type
)
200 ObsoleteAttribute obsolete_attr
= AttributeTester
.GetObsoleteAttribute (type
);
201 if (obsolete_attr
== null)
204 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, type
.FullName
, loc
);
208 /// Performs semantic analysis on the Expression
212 /// The Resolve method is invoked to perform the semantic analysis
215 /// The return value is an expression (it can be the
216 /// same expression in some cases) or a new
217 /// expression that better represents this node.
219 /// For example, optimizations of Unary (LiteralInt)
220 /// would return a new LiteralInt with a negated
223 /// If there is an error during semantic analysis,
224 /// then an error should be reported (using Report)
225 /// and a null value should be returned.
227 /// There are two side effects expected from calling
228 /// Resolve(): the the field variable "eclass" should
229 /// be set to any value of the enumeration
230 /// `ExprClass' and the type variable should be set
231 /// to a valid type (this is the type of the
234 public abstract Expression
DoResolve (EmitContext ec
);
236 public virtual Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
238 return DoResolve (ec
);
242 // This is used if the expression should be resolved as a type.
243 // the default implementation fails. Use this method in
244 // those participants in the SimpleName chain system.
246 public virtual Expression
ResolveAsTypeStep (EmitContext ec
)
252 // This is used to resolve the expression as a type, a null
253 // value will be returned if the expression is not a type
256 public TypeExpr
ResolveAsTypeTerminal (EmitContext ec
, bool silent
)
258 int errors
= Report
.Errors
;
260 TypeExpr te
= ResolveAsTypeStep (ec
) as TypeExpr
;
262 if (te
== null || te
.eclass
!= ExprClass
.Type
) {
263 if (!silent
&& errors
== Report
.Errors
)
264 Report
.Error (246, Location
, "Cannot find type '{0}'", ToString ());
268 if (!te
.CheckAccessLevel (ec
.DeclSpace
)) {
269 Report
.Error (122, Location
, "'{0}' is inaccessible due to its protection level", te
.Name
);
277 /// Resolves an expression and performs semantic analysis on it.
281 /// Currently Resolve wraps DoResolve to perform sanity
282 /// checking and assertion checking on what we expect from Resolve.
284 public Expression
Resolve (EmitContext ec
, ResolveFlags flags
)
286 if ((flags
& ResolveFlags
.MaskExprClass
) == ResolveFlags
.Type
)
287 return ResolveAsTypeStep (ec
);
289 bool old_do_flow_analysis
= ec
.DoFlowAnalysis
;
290 if ((flags
& ResolveFlags
.DisableFlowAnalysis
) != 0)
291 ec
.DoFlowAnalysis
= false;
294 bool intermediate
= (flags
& ResolveFlags
.Intermediate
) == ResolveFlags
.Intermediate
;
295 if (this is SimpleName
)
296 e
= ((SimpleName
) this).DoResolveAllowStatic (ec
, intermediate
);
301 ec
.DoFlowAnalysis
= old_do_flow_analysis
;
306 if (e
is SimpleName
){
307 SimpleName s
= (SimpleName
) e
;
309 if ((flags
& ResolveFlags
.SimpleName
) == 0) {
310 MemberLookupFailed (ec
, null, ec
.ContainerType
, s
.Name
,
311 ec
.DeclSpace
.Name
, loc
);
318 if ((e
is TypeExpr
) || (e
is ComposedCast
)) {
319 if ((flags
& ResolveFlags
.Type
) == 0) {
320 e
.Error_UnexpectedKind (flags
, loc
);
329 if ((flags
& ResolveFlags
.VariableOrValue
) == 0) {
330 e
.Error_UnexpectedKind (flags
, loc
);
335 case ExprClass
.MethodGroup
:
336 if (RootContext
.Version
== LanguageVersion
.ISO_1
){
337 if ((flags
& ResolveFlags
.MethodGroup
) == 0) {
338 ((MethodGroupExpr
) e
).ReportUsageError ();
344 case ExprClass
.Value
:
345 case ExprClass
.Variable
:
346 case ExprClass
.PropertyAccess
:
347 case ExprClass
.EventAccess
:
348 case ExprClass
.IndexerAccess
:
349 if ((flags
& ResolveFlags
.VariableOrValue
) == 0) {
350 Console
.WriteLine ("I got: {0} and {1}", e
.GetType (), e
);
351 Console
.WriteLine ("I am {0} and {1}", this.GetType (), this);
352 FieldInfo fi
= ((FieldExpr
) e
).FieldInfo
;
354 Console
.WriteLine ("{0} and {1}", fi
.DeclaringType
, fi
.Name
);
355 e
.Error_UnexpectedKind (flags
, loc
);
361 throw new Exception ("Expression " + e
.GetType () +
362 " ExprClass is Invalid after resolve");
366 throw new Exception (
367 "Expression " + e
.GetType () +
368 " did not set its type after Resolve\n" +
369 "called from: " + this.GetType ());
375 /// Resolves an expression and performs semantic analysis on it.
377 public Expression
Resolve (EmitContext ec
)
379 return Resolve (ec
, ResolveFlags
.VariableOrValue
);
383 /// Resolves an expression for LValue assignment
387 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
388 /// checking and assertion checking on what we expect from Resolve
390 public Expression
ResolveLValue (EmitContext ec
, Expression right_side
)
392 Expression e
= DoResolveLValue (ec
, right_side
);
395 if (e
is SimpleName
){
396 SimpleName s
= (SimpleName
) e
;
397 MemberLookupFailed (ec
, null, ec
.ContainerType
, s
.Name
,
398 ec
.DeclSpace
.Name
, loc
);
402 if (e
.eclass
== ExprClass
.Invalid
)
403 throw new Exception ("Expression " + e
+
404 " ExprClass is Invalid after resolve");
406 if (e
.eclass
== ExprClass
.MethodGroup
) {
407 ((MethodGroupExpr
) e
).ReportUsageError ();
412 throw new Exception ("Expression " + e
+
413 " did not set its type after Resolve");
420 /// Emits the code for the expression
424 /// The Emit method is invoked to generate the code
425 /// for the expression.
427 public abstract void Emit (EmitContext ec
);
429 public virtual void EmitBranchable (EmitContext ec
, Label target
, bool onTrue
)
432 ec
.ig
.Emit (onTrue
? OpCodes
.Brtrue
: OpCodes
.Brfalse
, target
);
436 /// Protected constructor. Only derivate types should
437 /// be able to be created
440 protected Expression ()
442 eclass
= ExprClass
.Invalid
;
447 /// Returns a literalized version of a literal FieldInfo
451 /// The possible return values are:
452 /// IntConstant, UIntConstant
453 /// LongLiteral, ULongConstant
454 /// FloatConstant, DoubleConstant
457 /// The value returned is already resolved.
459 public static Constant
Constantify (object v
, Type t
)
461 if (t
== TypeManager
.int32_type
)
462 return new IntConstant ((int) v
);
463 else if (t
== TypeManager
.uint32_type
)
464 return new UIntConstant ((uint) v
);
465 else if (t
== TypeManager
.int64_type
)
466 return new LongConstant ((long) v
);
467 else if (t
== TypeManager
.uint64_type
)
468 return new ULongConstant ((ulong) v
);
469 else if (t
== TypeManager
.float_type
)
470 return new FloatConstant ((float) v
);
471 else if (t
== TypeManager
.double_type
)
472 return new DoubleConstant ((double) v
);
473 else if (t
== TypeManager
.string_type
)
474 return new StringConstant ((string) v
);
475 else if (t
== TypeManager
.short_type
)
476 return new ShortConstant ((short)v
);
477 else if (t
== TypeManager
.ushort_type
)
478 return new UShortConstant ((ushort)v
);
479 else if (t
== TypeManager
.sbyte_type
)
480 return new SByteConstant (((sbyte)v
));
481 else if (t
== TypeManager
.byte_type
)
482 return new ByteConstant ((byte)v
);
483 else if (t
== TypeManager
.char_type
)
484 return new CharConstant ((char)v
);
485 else if (t
== TypeManager
.bool_type
)
486 return new BoolConstant ((bool) v
);
487 else if (TypeManager
.IsEnumType (t
)){
488 Type real_type
= TypeManager
.TypeToCoreType (v
.GetType ());
490 real_type
= System
.Enum
.GetUnderlyingType (real_type
);
492 Constant e
= Constantify (v
, real_type
);
494 return new EnumConstant (e
, t
);
495 } else if (v
== null && !TypeManager
.IsValueType (t
))
496 return NullLiteral
.Null
;
498 throw new Exception ("Unknown type for constant (" + t
+
503 /// Returns a fully formed expression after a MemberLookup
505 public static Expression
ExprClassFromMemberInfo (EmitContext ec
, MemberInfo mi
, Location loc
)
508 return new EventExpr ((EventInfo
) mi
, loc
);
509 else if (mi
is FieldInfo
)
510 return new FieldExpr ((FieldInfo
) mi
, loc
);
511 else if (mi
is PropertyInfo
)
512 return new PropertyExpr (ec
, (PropertyInfo
) mi
, loc
);
513 else if (mi
is Type
){
514 return new TypeExpression ((System
.Type
) mi
, loc
);
521 private static ArrayList almostMatchedMembers
= new ArrayList (4);
524 // FIXME: Probably implement a cache for (t,name,current_access_set)?
526 // This code could use some optimizations, but we need to do some
527 // measurements. For example, we could use a delegate to `flag' when
528 // something can not any longer be a method-group (because it is something
532 // If the return value is an Array, then it is an array of
535 // If the return value is an MemberInfo, it is anything, but a Method
539 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
540 // the arguments here and have MemberLookup return only the methods that
541 // match the argument count/type, unlike we are doing now (we delay this
544 // This is so we can catch correctly attempts to invoke instance methods
545 // from a static body (scan for error 120 in ResolveSimpleName).
548 // FIXME: Potential optimization, have a static ArrayList
551 public static Expression
MemberLookup (EmitContext ec
, Type queried_type
, string name
,
552 MemberTypes mt
, BindingFlags bf
, Location loc
)
554 return MemberLookup (ec
, ec
.ContainerType
, null, queried_type
, name
, mt
, bf
, loc
);
558 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
559 // `qualifier_type' or null to lookup members in the current class.
562 public static Expression
MemberLookup (EmitContext ec
, Type container_type
,
563 Type qualifier_type
, Type queried_type
,
564 string name
, MemberTypes mt
,
565 BindingFlags bf
, Location loc
)
567 almostMatchedMembers
.Clear ();
569 MemberInfo
[] mi
= TypeManager
.MemberLookup (container_type
, qualifier_type
,
570 queried_type
, mt
, bf
, name
, almostMatchedMembers
);
575 int count
= mi
.Length
;
577 if (mi
[0] is MethodBase
)
578 return new MethodGroupExpr (mi
, loc
);
583 return ExprClassFromMemberInfo (ec
, mi
[0], loc
);
586 public const MemberTypes AllMemberTypes
=
587 MemberTypes
.Constructor
|
591 MemberTypes
.NestedType
|
592 MemberTypes
.Property
;
594 public const BindingFlags AllBindingFlags
=
595 BindingFlags
.Public
|
596 BindingFlags
.Static
|
597 BindingFlags
.Instance
;
599 public static Expression
MemberLookup (EmitContext ec
, Type queried_type
,
600 string name
, Location loc
)
602 return MemberLookup (ec
, ec
.ContainerType
, null, queried_type
, name
,
603 AllMemberTypes
, AllBindingFlags
, loc
);
606 public static Expression
MemberLookup (EmitContext ec
, Type qualifier_type
,
607 Type queried_type
, string name
, Location loc
)
609 return MemberLookup (ec
, ec
.ContainerType
, qualifier_type
, queried_type
,
610 name
, AllMemberTypes
, AllBindingFlags
, loc
);
613 public static Expression
MethodLookup (EmitContext ec
, Type queried_type
,
614 string name
, Location loc
)
616 return MemberLookup (ec
, ec
.ContainerType
, null, queried_type
, name
,
617 MemberTypes
.Method
, AllBindingFlags
, loc
);
621 /// This is a wrapper for MemberLookup that is not used to "probe", but
622 /// to find a final definition. If the final definition is not found, we
623 /// look for private members and display a useful debugging message if we
626 public static Expression
MemberLookupFinal (EmitContext ec
, Type qualifier_type
,
627 Type queried_type
, string name
, Location loc
)
629 return MemberLookupFinal (ec
, qualifier_type
, queried_type
, name
,
630 AllMemberTypes
, AllBindingFlags
, loc
);
633 public static Expression
MemberLookupFinal (EmitContext ec
, Type qualifier_type
,
634 Type queried_type
, string name
,
635 MemberTypes mt
, BindingFlags bf
,
640 int errors
= Report
.Errors
;
642 e
= MemberLookup (ec
, ec
.ContainerType
, qualifier_type
, queried_type
, name
, mt
, bf
, loc
);
644 if (e
== null && errors
== Report
.Errors
)
645 // No errors were reported by MemberLookup, but there was an error.
646 MemberLookupFailed (ec
, qualifier_type
, queried_type
, name
, null, loc
);
651 public static void MemberLookupFailed (EmitContext ec
, Type qualifier_type
,
652 Type queried_type
, string name
,
653 string class_name
, Location loc
)
655 if (almostMatchedMembers
.Count
!= 0) {
656 if (qualifier_type
== null) {
657 foreach (MemberInfo m
in almostMatchedMembers
)
658 Report
.Error (38, loc
,
659 "Cannot access non-static member `{0}' via nested type `{1}'",
660 TypeManager
.GetFullNameSignature (m
),
661 TypeManager
.CSharpName (ec
.ContainerType
));
665 if (qualifier_type
!= ec
.ContainerType
) {
666 // Although a derived class can access protected members of
667 // its base class it cannot do so through an instance of the
668 // base class (CS1540). If the qualifier_type is a parent of the
669 // ec.ContainerType and the lookup succeeds with the latter one,
670 // then we are in this situation.
671 foreach (MemberInfo m
in almostMatchedMembers
)
672 Report
.Error (1540, loc
,
673 "Cannot access protected member `{0}' via a qualifier of type `{1}';"
674 + " the qualifier must be of type `{2}' (or derived from it)",
675 TypeManager
.GetFullNameSignature (m
),
676 TypeManager
.CSharpName (qualifier_type
),
677 TypeManager
.CSharpName (ec
.ContainerType
));
680 almostMatchedMembers
.Clear ();
683 object lookup
= TypeManager
.MemberLookup (queried_type
, null, queried_type
,
684 AllMemberTypes
, AllBindingFlags
|
685 BindingFlags
.NonPublic
, name
, null);
687 if (lookup
== null) {
688 if (class_name
!= null)
689 Report
.Error (103, loc
, "The name `" + name
+ "' could not be " +
690 "found in `" + class_name
+ "'");
693 117, loc
, "`" + queried_type
+ "' does not contain a " +
694 "definition for `" + name
+ "'");
698 if (qualifier_type
!= null)
699 Report
.Error (122, loc
, "'{0}' is inaccessible due to its protection level", TypeManager
.CSharpName (qualifier_type
) + "." + name
);
700 else if (name
== ".ctor") {
701 Report
.Error (143, loc
, String
.Format ("The type {0} has no constructors defined",
702 TypeManager
.CSharpName (queried_type
)));
704 Report
.Error (122, loc
, "'{0}' is inaccessible due to its protection level", name
);
708 static public MemberInfo
GetFieldFromEvent (EventExpr event_expr
)
710 EventInfo ei
= event_expr
.EventInfo
;
712 return TypeManager
.GetPrivateFieldOfEvent (ei
);
716 /// Returns an expression that can be used to invoke operator true
717 /// on the expression if it exists.
719 static public StaticCallExpr
GetOperatorTrue (EmitContext ec
, Expression e
, Location loc
)
721 return GetOperatorTrueOrFalse (ec
, e
, true, loc
);
725 /// Returns an expression that can be used to invoke operator false
726 /// on the expression if it exists.
728 static public StaticCallExpr
GetOperatorFalse (EmitContext ec
, Expression e
, Location loc
)
730 return GetOperatorTrueOrFalse (ec
, e
, false, loc
);
733 static StaticCallExpr
GetOperatorTrueOrFalse (EmitContext ec
, Expression e
, bool is_true
, Location loc
)
736 Expression operator_group
;
738 operator_group
= MethodLookup (ec
, e
.Type
, is_true
? "op_True" : "op_False", loc
);
739 if (operator_group
== null)
742 ArrayList arguments
= new ArrayList ();
743 arguments
.Add (new Argument (e
, Argument
.AType
.Expression
));
744 method
= Invocation
.OverloadResolve (
745 ec
, (MethodGroupExpr
) operator_group
, arguments
, false, loc
);
750 return new StaticCallExpr ((MethodInfo
) method
, arguments
, loc
);
754 /// Resolves the expression `e' into a boolean expression: either through
755 /// an implicit conversion, or through an `operator true' invocation
757 public static Expression
ResolveBoolean (EmitContext ec
, Expression e
, Location loc
)
763 Expression converted
= e
;
764 if (e
.Type
!= TypeManager
.bool_type
)
765 converted
= Convert
.ImplicitConversion (ec
, e
, TypeManager
.bool_type
, new Location (-1));
768 // If no implicit conversion to bool exists, try using `operator true'
770 if (converted
== null){
771 Expression operator_true
= Expression
.GetOperatorTrue (ec
, e
, loc
);
772 if (operator_true
== null){
774 31, loc
, "Can not convert the expression to a boolean");
784 static string ExprClassName (ExprClass c
)
787 case ExprClass
.Invalid
:
789 case ExprClass
.Value
:
791 case ExprClass
.Variable
:
793 case ExprClass
.Namespace
:
797 case ExprClass
.MethodGroup
:
798 return "method group";
799 case ExprClass
.PropertyAccess
:
800 return "property access";
801 case ExprClass
.EventAccess
:
802 return "event access";
803 case ExprClass
.IndexerAccess
:
804 return "indexer access";
805 case ExprClass
.Nothing
:
808 throw new Exception ("Should not happen");
812 /// Reports that we were expecting `expr' to be of class `expected'
814 public void Error_UnexpectedKind (string expected
, Location loc
)
816 string kind
= "Unknown";
818 kind
= ExprClassName (eclass
);
820 Report
.Error (118, loc
, "Expression denotes a `" + kind
+
821 "' where a `" + expected
+ "' was expected");
824 public void Error_UnexpectedKind (ResolveFlags flags
, Location loc
)
826 ArrayList valid
= new ArrayList (10);
828 if ((flags
& ResolveFlags
.VariableOrValue
) != 0) {
829 valid
.Add ("variable");
833 if ((flags
& ResolveFlags
.Type
) != 0)
836 if ((flags
& ResolveFlags
.MethodGroup
) != 0)
837 valid
.Add ("method group");
839 if ((flags
& ResolveFlags
.SimpleName
) != 0)
840 valid
.Add ("simple name");
842 if (valid
.Count
== 0)
843 valid
.Add ("unknown");
845 StringBuilder sb
= new StringBuilder ();
846 for (int i
= 0; i
< valid
.Count
; i
++) {
849 else if (i
== valid
.Count
)
851 sb
.Append (valid
[i
]);
854 string kind
= ExprClassName (eclass
);
856 Error (119, "Expression denotes a `" + kind
+ "' where " +
857 "a `" + sb
.ToString () + "' was expected");
860 static public void Error_ConstantValueCannotBeConverted (Location l
, string val
, Type t
)
862 Report
.Error (31, l
, "Constant value `" + val
+ "' cannot be converted to " +
863 TypeManager
.CSharpName (t
));
866 public static void UnsafeError (Location loc
)
868 Report
.Error (214, loc
, "Pointers may only be used in an unsafe context");
872 /// Converts the IntConstant, UIntConstant, LongConstant or
873 /// ULongConstant into the integral target_type. Notice
874 /// that we do not return an `Expression' we do return
875 /// a boxed integral type.
877 /// FIXME: Since I added the new constants, we need to
878 /// also support conversions from CharConstant, ByteConstant,
879 /// SByteConstant, UShortConstant, ShortConstant
881 /// This is used by the switch statement, so the domain
882 /// of work is restricted to the literals above, and the
883 /// targets are int32, uint32, char, byte, sbyte, ushort,
884 /// short, uint64 and int64
886 public static object ConvertIntLiteral (Constant c
, Type target_type
, Location loc
)
888 if (!Convert
.ImplicitStandardConversionExists (Convert
.ConstantEC
, c
, target_type
)){
889 Convert
.Error_CannotImplicitConversion (loc
, c
.Type
, target_type
);
895 if (c
.Type
== target_type
)
896 return ((Constant
) c
).GetValue ();
899 // Make into one of the literals we handle, we dont really care
900 // about this value as we will just return a few limited types
902 if (c
is EnumConstant
)
903 c
= ((EnumConstant
)c
).WidenToCompilerConstant ();
905 if (c
is IntConstant
){
906 int v
= ((IntConstant
) c
).Value
;
908 if (target_type
== TypeManager
.uint32_type
){
911 } else if (target_type
== TypeManager
.char_type
){
912 if (v
>= Char
.MinValue
&& v
<= Char
.MaxValue
)
914 } else if (target_type
== TypeManager
.byte_type
){
915 if (v
>= Byte
.MinValue
&& v
<= Byte
.MaxValue
)
917 } else if (target_type
== TypeManager
.sbyte_type
){
918 if (v
>= SByte
.MinValue
&& v
<= SByte
.MaxValue
)
920 } else if (target_type
== TypeManager
.short_type
){
921 if (v
>= Int16
.MinValue
&& v
<= UInt16
.MaxValue
)
923 } else if (target_type
== TypeManager
.ushort_type
){
924 if (v
>= UInt16
.MinValue
&& v
<= UInt16
.MaxValue
)
926 } else if (target_type
== TypeManager
.int64_type
)
928 else if (target_type
== TypeManager
.uint64_type
){
934 } else if (c
is UIntConstant
){
935 uint v
= ((UIntConstant
) c
).Value
;
937 if (target_type
== TypeManager
.int32_type
){
938 if (v
<= Int32
.MaxValue
)
940 } else if (target_type
== TypeManager
.char_type
){
941 if (v
>= Char
.MinValue
&& v
<= Char
.MaxValue
)
943 } else if (target_type
== TypeManager
.byte_type
){
944 if (v
<= Byte
.MaxValue
)
946 } else if (target_type
== TypeManager
.sbyte_type
){
947 if (v
<= SByte
.MaxValue
)
949 } else if (target_type
== TypeManager
.short_type
){
950 if (v
<= UInt16
.MaxValue
)
952 } else if (target_type
== TypeManager
.ushort_type
){
953 if (v
<= UInt16
.MaxValue
)
955 } else if (target_type
== TypeManager
.int64_type
)
957 else if (target_type
== TypeManager
.uint64_type
)
960 } else if (c
is LongConstant
){
961 long v
= ((LongConstant
) c
).Value
;
963 if (target_type
== TypeManager
.int32_type
){
964 if (v
>= UInt32
.MinValue
&& v
<= UInt32
.MaxValue
)
966 } else if (target_type
== TypeManager
.uint32_type
){
967 if (v
>= 0 && v
<= UInt32
.MaxValue
)
969 } else if (target_type
== TypeManager
.char_type
){
970 if (v
>= Char
.MinValue
&& v
<= Char
.MaxValue
)
972 } else if (target_type
== TypeManager
.byte_type
){
973 if (v
>= Byte
.MinValue
&& v
<= Byte
.MaxValue
)
975 } else if (target_type
== TypeManager
.sbyte_type
){
976 if (v
>= SByte
.MinValue
&& v
<= SByte
.MaxValue
)
978 } else if (target_type
== TypeManager
.short_type
){
979 if (v
>= Int16
.MinValue
&& v
<= UInt16
.MaxValue
)
981 } else if (target_type
== TypeManager
.ushort_type
){
982 if (v
>= UInt16
.MinValue
&& v
<= UInt16
.MaxValue
)
984 } else if (target_type
== TypeManager
.uint64_type
){
989 } else if (c
is ULongConstant
){
990 ulong v
= ((ULongConstant
) c
).Value
;
992 if (target_type
== TypeManager
.int32_type
){
993 if (v
<= Int32
.MaxValue
)
995 } else if (target_type
== TypeManager
.uint32_type
){
996 if (v
<= UInt32
.MaxValue
)
998 } else if (target_type
== TypeManager
.char_type
){
999 if (v
>= Char
.MinValue
&& v
<= Char
.MaxValue
)
1001 } else if (target_type
== TypeManager
.byte_type
){
1002 if (v
>= Byte
.MinValue
&& v
<= Byte
.MaxValue
)
1004 } else if (target_type
== TypeManager
.sbyte_type
){
1005 if (v
<= (int) SByte
.MaxValue
)
1007 } else if (target_type
== TypeManager
.short_type
){
1008 if (v
<= UInt16
.MaxValue
)
1010 } else if (target_type
== TypeManager
.ushort_type
){
1011 if (v
<= UInt16
.MaxValue
)
1013 } else if (target_type
== TypeManager
.int64_type
){
1014 if (v
<= Int64
.MaxValue
)
1018 } else if (c
is ByteConstant
){
1019 byte v
= ((ByteConstant
) c
).Value
;
1021 if (target_type
== TypeManager
.int32_type
)
1023 else if (target_type
== TypeManager
.uint32_type
)
1025 else if (target_type
== TypeManager
.char_type
)
1027 else if (target_type
== TypeManager
.sbyte_type
){
1028 if (v
<= SByte
.MaxValue
)
1030 } else if (target_type
== TypeManager
.short_type
)
1032 else if (target_type
== TypeManager
.ushort_type
)
1034 else if (target_type
== TypeManager
.int64_type
)
1036 else if (target_type
== TypeManager
.uint64_type
)
1039 } else if (c
is SByteConstant
){
1040 sbyte v
= ((SByteConstant
) c
).Value
;
1042 if (target_type
== TypeManager
.int32_type
)
1044 else if (target_type
== TypeManager
.uint32_type
){
1047 } else if (target_type
== TypeManager
.char_type
){
1050 } else if (target_type
== TypeManager
.byte_type
){
1053 } else if (target_type
== TypeManager
.short_type
)
1055 else if (target_type
== TypeManager
.ushort_type
){
1058 } else if (target_type
== TypeManager
.int64_type
)
1060 else if (target_type
== TypeManager
.uint64_type
){
1065 } else if (c
is ShortConstant
){
1066 short v
= ((ShortConstant
) c
).Value
;
1068 if (target_type
== TypeManager
.int32_type
){
1070 } else if (target_type
== TypeManager
.uint32_type
){
1073 } else if (target_type
== TypeManager
.char_type
){
1076 } else if (target_type
== TypeManager
.byte_type
){
1077 if (v
>= Byte
.MinValue
&& v
<= Byte
.MaxValue
)
1079 } else if (target_type
== TypeManager
.sbyte_type
){
1080 if (v
>= SByte
.MinValue
&& v
<= SByte
.MaxValue
)
1082 } else if (target_type
== TypeManager
.ushort_type
){
1085 } else if (target_type
== TypeManager
.int64_type
)
1087 else if (target_type
== TypeManager
.uint64_type
)
1091 } else if (c
is UShortConstant
){
1092 ushort v
= ((UShortConstant
) c
).Value
;
1094 if (target_type
== TypeManager
.int32_type
)
1096 else if (target_type
== TypeManager
.uint32_type
)
1098 else if (target_type
== TypeManager
.char_type
){
1099 if (v
>= Char
.MinValue
&& v
<= Char
.MaxValue
)
1101 } else if (target_type
== TypeManager
.byte_type
){
1102 if (v
>= Byte
.MinValue
&& v
<= Byte
.MaxValue
)
1104 } else if (target_type
== TypeManager
.sbyte_type
){
1105 if (v
<= SByte
.MaxValue
)
1107 } else if (target_type
== TypeManager
.short_type
){
1108 if (v
<= Int16
.MaxValue
)
1110 } else if (target_type
== TypeManager
.int64_type
)
1112 else if (target_type
== TypeManager
.uint64_type
)
1116 } else if (c
is CharConstant
){
1117 char v
= ((CharConstant
) c
).Value
;
1119 if (target_type
== TypeManager
.int32_type
)
1121 else if (target_type
== TypeManager
.uint32_type
)
1123 else if (target_type
== TypeManager
.byte_type
){
1124 if (v
>= Byte
.MinValue
&& v
<= Byte
.MaxValue
)
1126 } else if (target_type
== TypeManager
.sbyte_type
){
1127 if (v
<= SByte
.MaxValue
)
1129 } else if (target_type
== TypeManager
.short_type
){
1130 if (v
<= Int16
.MaxValue
)
1132 } else if (target_type
== TypeManager
.ushort_type
)
1134 else if (target_type
== TypeManager
.int64_type
)
1136 else if (target_type
== TypeManager
.uint64_type
)
1141 Error_ConstantValueCannotBeConverted (loc
, s
, target_type
);
1146 // Load the object from the pointer.
1148 public static void LoadFromPtr (ILGenerator ig
, Type t
)
1150 if (t
== TypeManager
.int32_type
)
1151 ig
.Emit (OpCodes
.Ldind_I4
);
1152 else if (t
== TypeManager
.uint32_type
)
1153 ig
.Emit (OpCodes
.Ldind_U4
);
1154 else if (t
== TypeManager
.short_type
)
1155 ig
.Emit (OpCodes
.Ldind_I2
);
1156 else if (t
== TypeManager
.ushort_type
)
1157 ig
.Emit (OpCodes
.Ldind_U2
);
1158 else if (t
== TypeManager
.char_type
)
1159 ig
.Emit (OpCodes
.Ldind_U2
);
1160 else if (t
== TypeManager
.byte_type
)
1161 ig
.Emit (OpCodes
.Ldind_U1
);
1162 else if (t
== TypeManager
.sbyte_type
)
1163 ig
.Emit (OpCodes
.Ldind_I1
);
1164 else if (t
== TypeManager
.uint64_type
)
1165 ig
.Emit (OpCodes
.Ldind_I8
);
1166 else if (t
== TypeManager
.int64_type
)
1167 ig
.Emit (OpCodes
.Ldind_I8
);
1168 else if (t
== TypeManager
.float_type
)
1169 ig
.Emit (OpCodes
.Ldind_R4
);
1170 else if (t
== TypeManager
.double_type
)
1171 ig
.Emit (OpCodes
.Ldind_R8
);
1172 else if (t
== TypeManager
.bool_type
)
1173 ig
.Emit (OpCodes
.Ldind_I1
);
1174 else if (t
== TypeManager
.intptr_type
)
1175 ig
.Emit (OpCodes
.Ldind_I
);
1176 else if (TypeManager
.IsEnumType (t
)) {
1177 if (t
== TypeManager
.enum_type
)
1178 ig
.Emit (OpCodes
.Ldind_Ref
);
1180 LoadFromPtr (ig
, TypeManager
.EnumToUnderlying (t
));
1181 } else if (t
.IsValueType
)
1182 ig
.Emit (OpCodes
.Ldobj
, t
);
1183 else if (t
.IsPointer
)
1184 ig
.Emit (OpCodes
.Ldind_I
);
1186 ig
.Emit (OpCodes
.Ldind_Ref
);
1190 // The stack contains the pointer and the value of type `type'
1192 public static void StoreFromPtr (ILGenerator ig
, Type type
)
1194 if (TypeManager
.IsEnumType (type
))
1195 type
= TypeManager
.EnumToUnderlying (type
);
1196 if (type
== TypeManager
.int32_type
|| type
== TypeManager
.uint32_type
)
1197 ig
.Emit (OpCodes
.Stind_I4
);
1198 else if (type
== TypeManager
.int64_type
|| type
== TypeManager
.uint64_type
)
1199 ig
.Emit (OpCodes
.Stind_I8
);
1200 else if (type
== TypeManager
.char_type
|| type
== TypeManager
.short_type
||
1201 type
== TypeManager
.ushort_type
)
1202 ig
.Emit (OpCodes
.Stind_I2
);
1203 else if (type
== TypeManager
.float_type
)
1204 ig
.Emit (OpCodes
.Stind_R4
);
1205 else if (type
== TypeManager
.double_type
)
1206 ig
.Emit (OpCodes
.Stind_R8
);
1207 else if (type
== TypeManager
.byte_type
|| type
== TypeManager
.sbyte_type
||
1208 type
== TypeManager
.bool_type
)
1209 ig
.Emit (OpCodes
.Stind_I1
);
1210 else if (type
== TypeManager
.intptr_type
)
1211 ig
.Emit (OpCodes
.Stind_I
);
1212 else if (type
.IsValueType
)
1213 ig
.Emit (OpCodes
.Stobj
, type
);
1215 ig
.Emit (OpCodes
.Stind_Ref
);
1219 // Returns the size of type `t' if known, otherwise, 0
1221 public static int GetTypeSize (Type t
)
1223 t
= TypeManager
.TypeToCoreType (t
);
1224 if (t
== TypeManager
.int32_type
||
1225 t
== TypeManager
.uint32_type
||
1226 t
== TypeManager
.float_type
)
1228 else if (t
== TypeManager
.int64_type
||
1229 t
== TypeManager
.uint64_type
||
1230 t
== TypeManager
.double_type
)
1232 else if (t
== TypeManager
.byte_type
||
1233 t
== TypeManager
.sbyte_type
||
1234 t
== TypeManager
.bool_type
)
1236 else if (t
== TypeManager
.short_type
||
1237 t
== TypeManager
.char_type
||
1238 t
== TypeManager
.ushort_type
)
1240 else if (t
== TypeManager
.decimal_type
)
1246 public static void Error_NegativeArrayIndex (Location loc
)
1248 Report
.Error (248, loc
, "Cannot create an array with a negative size");
1252 // Converts `source' to an int, uint, long or ulong.
1254 public Expression
ExpressionToArrayArgument (EmitContext ec
, Expression source
, Location loc
)
1258 bool old_checked
= ec
.CheckState
;
1259 ec
.CheckState
= true;
1261 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.int32_type
, loc
);
1262 if (target
== null){
1263 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.uint32_type
, loc
);
1264 if (target
== null){
1265 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.int64_type
, loc
);
1266 if (target
== null){
1267 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.uint64_type
, loc
);
1269 Convert
.Error_CannotImplicitConversion (loc
, source
.Type
, TypeManager
.int32_type
);
1273 ec
.CheckState
= old_checked
;
1276 // Only positive constants are allowed at compile time
1278 if (target
is Constant
){
1279 if (target
is IntConstant
){
1280 if (((IntConstant
) target
).Value
< 0){
1281 Error_NegativeArrayIndex (loc
);
1286 if (target
is LongConstant
){
1287 if (((LongConstant
) target
).Value
< 0){
1288 Error_NegativeArrayIndex (loc
);
1301 /// This is just a base class for expressions that can
1302 /// appear on statements (invocations, object creation,
1303 /// assignments, post/pre increment and decrement). The idea
1304 /// being that they would support an extra Emition interface that
1305 /// does not leave a result on the stack.
1307 public abstract class ExpressionStatement
: Expression
{
1309 public virtual ExpressionStatement
ResolveStatement (EmitContext ec
)
1311 Expression e
= Resolve (ec
);
1315 ExpressionStatement es
= e
as ExpressionStatement
;
1317 Error (201, "Only assignment, call, increment, decrement and new object " +
1318 "expressions can be used as a statement");
1324 /// Requests the expression to be emitted in a `statement'
1325 /// context. This means that no new value is left on the
1326 /// stack after invoking this method (constrasted with
1327 /// Emit that will always leave a value on the stack).
1329 public abstract void EmitStatement (EmitContext ec
);
1333 /// This kind of cast is used to encapsulate the child
1334 /// whose type is child.Type into an expression that is
1335 /// reported to return "return_type". This is used to encapsulate
1336 /// expressions which have compatible types, but need to be dealt
1337 /// at higher levels with.
1339 /// For example, a "byte" expression could be encapsulated in one
1340 /// of these as an "unsigned int". The type for the expression
1341 /// would be "unsigned int".
1344 public class EmptyCast
: Expression
{
1345 protected Expression child
;
1347 public Expression Child
{
1353 public EmptyCast (Expression child
, Type return_type
)
1355 eclass
= child
.eclass
;
1360 public override Expression
DoResolve (EmitContext ec
)
1362 // This should never be invoked, we are born in fully
1363 // initialized state.
1368 public override void Emit (EmitContext ec
)
1375 // We need to special case this since an empty cast of
1376 // a NullLiteral is still a Constant
1378 public class NullCast
: Constant
{
1379 protected Expression child
;
1381 public NullCast (Expression child
, Type return_type
)
1383 eclass
= child
.eclass
;
1388 override public string AsString ()
1393 public override object GetValue ()
1398 public override Expression
DoResolve (EmitContext ec
)
1400 // This should never be invoked, we are born in fully
1401 // initialized state.
1406 public override void Emit (EmitContext ec
)
1411 public override bool IsNegative
{
1420 /// This class is used to wrap literals which belong inside Enums
1422 public class EnumConstant
: Constant
{
1423 public Constant Child
;
1425 public EnumConstant (Constant child
, Type enum_type
)
1427 eclass
= child
.eclass
;
1432 public override Expression
DoResolve (EmitContext ec
)
1434 // This should never be invoked, we are born in fully
1435 // initialized state.
1440 public override void Emit (EmitContext ec
)
1445 public override object GetValue ()
1447 return Child
.GetValue ();
1450 public object GetValueAsEnumType ()
1452 return System
.Enum
.ToObject (type
, Child
.GetValue ());
1456 // Converts from one of the valid underlying types for an enumeration
1457 // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to
1458 // one of the internal compiler literals: Int/UInt/Long/ULong Literals.
1460 public Constant
WidenToCompilerConstant ()
1462 Type t
= TypeManager
.EnumToUnderlying (Child
.Type
);
1463 object v
= ((Constant
) Child
).GetValue ();;
1465 if (t
== TypeManager
.int32_type
)
1466 return new IntConstant ((int) v
);
1467 if (t
== TypeManager
.uint32_type
)
1468 return new UIntConstant ((uint) v
);
1469 if (t
== TypeManager
.int64_type
)
1470 return new LongConstant ((long) v
);
1471 if (t
== TypeManager
.uint64_type
)
1472 return new ULongConstant ((ulong) v
);
1473 if (t
== TypeManager
.short_type
)
1474 return new ShortConstant ((short) v
);
1475 if (t
== TypeManager
.ushort_type
)
1476 return new UShortConstant ((ushort) v
);
1477 if (t
== TypeManager
.byte_type
)
1478 return new ByteConstant ((byte) v
);
1479 if (t
== TypeManager
.sbyte_type
)
1480 return new SByteConstant ((sbyte) v
);
1482 throw new Exception ("Invalid enumeration underlying type: " + t
);
1486 // Extracts the value in the enumeration on its native representation
1488 public object GetPlainValue ()
1490 Type t
= TypeManager
.EnumToUnderlying (Child
.Type
);
1491 object v
= ((Constant
) Child
).GetValue ();;
1493 if (t
== TypeManager
.int32_type
)
1495 if (t
== TypeManager
.uint32_type
)
1497 if (t
== TypeManager
.int64_type
)
1499 if (t
== TypeManager
.uint64_type
)
1501 if (t
== TypeManager
.short_type
)
1503 if (t
== TypeManager
.ushort_type
)
1505 if (t
== TypeManager
.byte_type
)
1507 if (t
== TypeManager
.sbyte_type
)
1513 public override string AsString ()
1515 return Child
.AsString ();
1518 public override DoubleConstant
ConvertToDouble ()
1520 return Child
.ConvertToDouble ();
1523 public override FloatConstant
ConvertToFloat ()
1525 return Child
.ConvertToFloat ();
1528 public override ULongConstant
ConvertToULong ()
1530 return Child
.ConvertToULong ();
1533 public override LongConstant
ConvertToLong ()
1535 return Child
.ConvertToLong ();
1538 public override UIntConstant
ConvertToUInt ()
1540 return Child
.ConvertToUInt ();
1543 public override IntConstant
ConvertToInt ()
1545 return Child
.ConvertToInt ();
1548 public override bool IsZeroInteger
{
1549 get { return Child.IsZeroInteger; }
1552 public override bool IsNegative
{
1554 return Child
.IsNegative
;
1560 /// This kind of cast is used to encapsulate Value Types in objects.
1562 /// The effect of it is to box the value type emitted by the previous
1565 public class BoxedCast
: EmptyCast
{
1567 public BoxedCast (Expression expr
)
1568 : base (expr
, TypeManager
.object_type
)
1570 eclass
= ExprClass
.Value
;
1573 public BoxedCast (Expression expr
, Type target_type
)
1574 : base (expr
, target_type
)
1576 eclass
= ExprClass
.Value
;
1579 public override Expression
DoResolve (EmitContext ec
)
1581 // This should never be invoked, we are born in fully
1582 // initialized state.
1587 public override void Emit (EmitContext ec
)
1591 ec
.ig
.Emit (OpCodes
.Box
, child
.Type
);
1595 public class UnboxCast
: EmptyCast
{
1596 public UnboxCast (Expression expr
, Type return_type
)
1597 : base (expr
, return_type
)
1601 public override Expression
DoResolve (EmitContext ec
)
1603 // This should never be invoked, we are born in fully
1604 // initialized state.
1609 public override void Emit (EmitContext ec
)
1612 ILGenerator ig
= ec
.ig
;
1615 ig
.Emit (OpCodes
.Unbox
, t
);
1617 LoadFromPtr (ig
, t
);
1622 /// This is used to perform explicit numeric conversions.
1624 /// Explicit numeric conversions might trigger exceptions in a checked
1625 /// context, so they should generate the conv.ovf opcodes instead of
1628 public class ConvCast
: EmptyCast
{
1629 public enum Mode
: byte {
1630 I1_U1
, I1_U2
, I1_U4
, I1_U8
, I1_CH
,
1632 I2_I1
, I2_U1
, I2_U2
, I2_U4
, I2_U8
, I2_CH
,
1633 U2_I1
, U2_U1
, U2_I2
, U2_CH
,
1634 I4_I1
, I4_U1
, I4_I2
, I4_U2
, I4_U4
, I4_U8
, I4_CH
,
1635 U4_I1
, U4_U1
, U4_I2
, U4_U2
, U4_I4
, U4_CH
,
1636 I8_I1
, I8_U1
, I8_I2
, I8_U2
, I8_I4
, I8_U4
, I8_U8
, I8_CH
,
1637 U8_I1
, U8_U1
, U8_I2
, U8_U2
, U8_I4
, U8_U4
, U8_I8
, U8_CH
,
1638 CH_I1
, CH_U1
, CH_I2
,
1639 R4_I1
, R4_U1
, R4_I2
, R4_U2
, R4_I4
, R4_U4
, R4_I8
, R4_U8
, R4_CH
,
1640 R8_I1
, R8_U1
, R8_I2
, R8_U2
, R8_I4
, R8_U4
, R8_I8
, R8_U8
, R8_CH
, R8_R4
1646 public ConvCast (EmitContext ec
, Expression child
, Type return_type
, Mode m
)
1647 : base (child
, return_type
)
1649 checked_state
= ec
.CheckState
;
1653 public override Expression
DoResolve (EmitContext ec
)
1655 // This should never be invoked, we are born in fully
1656 // initialized state.
1661 public override string ToString ()
1663 return String
.Format ("ConvCast ({0}, {1})", mode
, child
);
1666 public override void Emit (EmitContext ec
)
1668 ILGenerator ig
= ec
.ig
;
1674 case Mode
.I1_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1675 case Mode
.I1_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1676 case Mode
.I1_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1677 case Mode
.I1_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1678 case Mode
.I1_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1680 case Mode
.U1_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1681 case Mode
.U1_CH
: /* nothing */ break;
1683 case Mode
.I2_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1684 case Mode
.I2_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1685 case Mode
.I2_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1686 case Mode
.I2_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1687 case Mode
.I2_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1688 case Mode
.I2_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1690 case Mode
.U2_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1691 case Mode
.U2_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1692 case Mode
.U2_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1693 case Mode
.U2_CH
: /* nothing */ break;
1695 case Mode
.I4_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1696 case Mode
.I4_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1697 case Mode
.I4_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1698 case Mode
.I4_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1699 case Mode
.I4_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1700 case Mode
.I4_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1701 case Mode
.I4_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1703 case Mode
.U4_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1704 case Mode
.U4_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1705 case Mode
.U4_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1706 case Mode
.U4_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1707 case Mode
.U4_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4_Un
); break;
1708 case Mode
.U4_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1710 case Mode
.I8_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1711 case Mode
.I8_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1712 case Mode
.I8_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1713 case Mode
.I8_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1714 case Mode
.I8_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4
); break;
1715 case Mode
.I8_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1716 case Mode
.I8_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1717 case Mode
.I8_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1719 case Mode
.U8_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1720 case Mode
.U8_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1721 case Mode
.U8_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1722 case Mode
.U8_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1723 case Mode
.U8_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4_Un
); break;
1724 case Mode
.U8_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4_Un
); break;
1725 case Mode
.U8_I8
: ig
.Emit (OpCodes
.Conv_Ovf_I8_Un
); break;
1726 case Mode
.U8_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1728 case Mode
.CH_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1729 case Mode
.CH_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1730 case Mode
.CH_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1732 case Mode
.R4_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1733 case Mode
.R4_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1734 case Mode
.R4_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1735 case Mode
.R4_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1736 case Mode
.R4_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4
); break;
1737 case Mode
.R4_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1738 case Mode
.R4_I8
: ig
.Emit (OpCodes
.Conv_Ovf_I8
); break;
1739 case Mode
.R4_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1740 case Mode
.R4_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1742 case Mode
.R8_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1743 case Mode
.R8_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1744 case Mode
.R8_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1745 case Mode
.R8_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1746 case Mode
.R8_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4
); break;
1747 case Mode
.R8_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1748 case Mode
.R8_I8
: ig
.Emit (OpCodes
.Conv_Ovf_I8
); break;
1749 case Mode
.R8_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1750 case Mode
.R8_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1751 case Mode
.R8_R4
: ig
.Emit (OpCodes
.Conv_R4
); break;
1755 case Mode
.I1_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1756 case Mode
.I1_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1757 case Mode
.I1_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1758 case Mode
.I1_U8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1759 case Mode
.I1_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1761 case Mode
.U1_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1762 case Mode
.U1_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1764 case Mode
.I2_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1765 case Mode
.I2_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1766 case Mode
.I2_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1767 case Mode
.I2_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1768 case Mode
.I2_U8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1769 case Mode
.I2_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1771 case Mode
.U2_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1772 case Mode
.U2_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1773 case Mode
.U2_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1774 case Mode
.U2_CH
: /* nothing */ break;
1776 case Mode
.I4_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1777 case Mode
.I4_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1778 case Mode
.I4_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1779 case Mode
.I4_U4
: /* nothing */ break;
1780 case Mode
.I4_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1781 case Mode
.I4_U8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1782 case Mode
.I4_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1784 case Mode
.U4_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1785 case Mode
.U4_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1786 case Mode
.U4_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1787 case Mode
.U4_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1788 case Mode
.U4_I4
: /* nothing */ break;
1789 case Mode
.U4_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1791 case Mode
.I8_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1792 case Mode
.I8_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1793 case Mode
.I8_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1794 case Mode
.I8_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1795 case Mode
.I8_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1796 case Mode
.I8_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1797 case Mode
.I8_U8
: /* nothing */ break;
1798 case Mode
.I8_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1800 case Mode
.U8_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1801 case Mode
.U8_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1802 case Mode
.U8_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1803 case Mode
.U8_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1804 case Mode
.U8_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1805 case Mode
.U8_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1806 case Mode
.U8_I8
: /* nothing */ break;
1807 case Mode
.U8_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1809 case Mode
.CH_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1810 case Mode
.CH_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1811 case Mode
.CH_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1813 case Mode
.R4_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1814 case Mode
.R4_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1815 case Mode
.R4_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1816 case Mode
.R4_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1817 case Mode
.R4_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1818 case Mode
.R4_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1819 case Mode
.R4_I8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1820 case Mode
.R4_U8
: ig
.Emit (OpCodes
.Conv_U8
); break;
1821 case Mode
.R4_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1823 case Mode
.R8_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1824 case Mode
.R8_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1825 case Mode
.R8_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1826 case Mode
.R8_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1827 case Mode
.R8_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1828 case Mode
.R8_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1829 case Mode
.R8_I8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1830 case Mode
.R8_U8
: ig
.Emit (OpCodes
.Conv_U8
); break;
1831 case Mode
.R8_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1832 case Mode
.R8_R4
: ig
.Emit (OpCodes
.Conv_R4
); break;
1838 public class OpcodeCast
: EmptyCast
{
1842 public OpcodeCast (Expression child
, Type return_type
, OpCode op
)
1843 : base (child
, return_type
)
1847 second_valid
= false;
1850 public OpcodeCast (Expression child
, Type return_type
, OpCode op
, OpCode op2
)
1851 : base (child
, return_type
)
1856 second_valid
= true;
1859 public override Expression
DoResolve (EmitContext ec
)
1861 // This should never be invoked, we are born in fully
1862 // initialized state.
1867 public override void Emit (EmitContext ec
)
1878 /// This kind of cast is used to encapsulate a child and cast it
1879 /// to the class requested
1881 public class ClassCast
: EmptyCast
{
1882 public ClassCast (Expression child
, Type return_type
)
1883 : base (child
, return_type
)
1888 public override Expression
DoResolve (EmitContext ec
)
1890 // This should never be invoked, we are born in fully
1891 // initialized state.
1896 public override void Emit (EmitContext ec
)
1900 ec
.ig
.Emit (OpCodes
.Castclass
, type
);
1906 /// SimpleName expressions are initially formed of a single
1907 /// word and it only happens at the beginning of the expression.
1911 /// The expression will try to be bound to a Field, a Method
1912 /// group or a Property. If those fail we pass the name to our
1913 /// caller and the SimpleName is compounded to perform a type
1914 /// lookup. The idea behind this process is that we want to avoid
1915 /// creating a namespace map from the assemblies, as that requires
1916 /// the GetExportedTypes function to be called and a hashtable to
1917 /// be constructed which reduces startup time. If later we find
1918 /// that this is slower, we should create a `NamespaceExpr' expression
1919 /// that fully participates in the resolution process.
1921 /// For example `System.Console.WriteLine' is decomposed into
1922 /// MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
1924 /// The first SimpleName wont produce a match on its own, so it will
1926 /// MemberAccess (SimpleName ("System.Console"), "WriteLine").
1928 /// System.Console will produce a TypeExpr match.
1930 /// The downside of this is that we might be hitting `LookupType' too many
1931 /// times with this scheme.
1933 public class SimpleName
: Expression
{
1937 // If true, then we are a simple name, not composed with a ".
1941 public SimpleName (string a
, string b
, Location l
)
1943 Name
= String
.Concat (a
, ".", b
);
1948 public SimpleName (string name
, Location l
)
1955 public static void Error_ObjectRefRequired (EmitContext ec
, Location l
, string name
)
1957 if (ec
.IsFieldInitializer
)
1960 "A field initializer cannot reference the non-static field, " +
1961 "method or property `"+name
+"'");
1965 "An object reference is required " +
1966 "for the non-static field `"+name
+"'");
1970 // Checks whether we are trying to access an instance
1971 // property, method or field from a static body.
1973 Expression
MemberStaticCheck (EmitContext ec
, Expression e
)
1975 if (e
is IMemberExpr
){
1976 IMemberExpr member
= (IMemberExpr
) e
;
1978 if (!member
.IsStatic
){
1979 Error_ObjectRefRequired (ec
, loc
, Name
);
1987 public override Expression
DoResolve (EmitContext ec
)
1989 return SimpleNameResolve (ec
, null, false, false);
1992 public override Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
1994 return SimpleNameResolve (ec
, right_side
, false, false);
1998 public Expression
DoResolveAllowStatic (EmitContext ec
, bool intermediate
)
2000 return SimpleNameResolve (ec
, null, true, intermediate
);
2003 public override Expression
ResolveAsTypeStep (EmitContext ec
)
2005 DeclSpace ds
= ec
.DeclSpace
;
2006 NamespaceEntry ns
= ds
.NamespaceEntry
;
2011 // Since we are cheating: we only do the Alias lookup for
2012 // namespaces if the name does not include any dots in it
2014 if (ns
!= null && is_base
)
2015 alias_value
= ns
.LookupAlias (Name
);
2019 if (ec
.ResolvingTypeTree
){
2020 int errors
= Report
.Errors
;
2021 Type dt
= ds
.FindType (loc
, Name
);
2023 if (Report
.Errors
!= errors
)
2027 return new TypeExpression (dt
, loc
);
2029 if (alias_value
!= null){
2030 if ((t
= RootContext
.LookupType (ds
, alias_value
, true, loc
)) != null)
2031 return new TypeExpression (t
, loc
);
2035 if ((t
= RootContext
.LookupType (ds
, Name
, true, loc
)) != null)
2036 return new TypeExpression (t
, loc
);
2038 if (alias_value
!= null) {
2039 if ((t
= RootContext
.LookupType (ds
, alias_value
, true, loc
)) != null)
2040 return new TypeExpression (t
, loc
);
2042 // we have alias value, but it isn't Type, so try if it's namespace
2043 return new SimpleName (alias_value
, loc
);
2046 // No match, maybe our parent can compose us
2047 // into something meaningful.
2051 Expression
SimpleNameResolve (EmitContext ec
, Expression right_side
,
2052 bool allow_static
, bool intermediate
)
2054 Expression e
= DoSimpleNameResolve (ec
, right_side
, allow_static
, intermediate
);
2058 Block current_block
= ec
.CurrentBlock
;
2059 if (current_block
!= null){
2060 //LocalInfo vi = current_block.GetLocalInfo (Name);
2062 current_block
.IsVariableNameUsedInChildBlock(Name
)) {
2063 Report
.Error (135, Location
,
2064 "'{0}' has a different meaning in a " +
2065 "child block", Name
);
2074 /// 7.5.2: Simple Names.
2076 /// Local Variables and Parameters are handled at
2077 /// parse time, so they never occur as SimpleNames.
2079 /// The `allow_static' flag is used by MemberAccess only
2080 /// and it is used to inform us that it is ok for us to
2081 /// avoid the static check, because MemberAccess might end
2082 /// up resolving the Name as a Type name and the access as
2083 /// a static type access.
2085 /// ie: Type Type; .... { Type.GetType (""); }
2087 /// Type is both an instance variable and a Type; Type.GetType
2088 /// is the static method not an instance method of type.
2090 Expression
DoSimpleNameResolve (EmitContext ec
, Expression right_side
, bool allow_static
, bool intermediate
)
2092 Expression e
= null;
2095 // Stage 1: Performed by the parser (binding to locals or parameters).
2097 Block current_block
= ec
.CurrentBlock
;
2098 if (current_block
!= null){
2099 LocalInfo vi
= current_block
.GetLocalInfo (Name
);
2103 var = new LocalVariableReference (ec
.CurrentBlock
, Name
, loc
);
2105 if (right_side
!= null)
2106 return var.ResolveLValue (ec
, right_side
);
2108 return var.Resolve (ec
);
2111 ParameterReference pref
= current_block
.GetParameterReference (Name
, loc
);
2113 if (right_side
!= null)
2114 return pref
.ResolveLValue (ec
, right_side
);
2116 return pref
.Resolve (ec
);
2121 // Stage 2: Lookup members
2124 DeclSpace lookup_ds
= ec
.DeclSpace
;
2126 if (lookup_ds
.TypeBuilder
== null)
2129 e
= MemberLookup (ec
, lookup_ds
.TypeBuilder
, Name
, loc
);
2133 lookup_ds
=lookup_ds
.Parent
;
2134 } while (lookup_ds
!= null);
2136 if (e
== null && ec
.ContainerType
!= null)
2137 e
= MemberLookup (ec
, ec
.ContainerType
, Name
, loc
);
2141 // Since we are cheating (is_base is our hint
2142 // that we are the beginning of the name): we
2143 // only do the Alias lookup for namespaces if
2144 // the name does not include any dots in it
2146 NamespaceEntry ns
= ec
.DeclSpace
.NamespaceEntry
;
2147 if (is_base
&& ns
!= null){
2148 string alias_value
= ns
.LookupAlias (Name
);
2149 if (alias_value
!= null){
2153 if ((t
= TypeManager
.LookupType (Name
)) != null)
2154 return new TypeExpression (t
, loc
);
2156 // No match, maybe our parent can compose us
2157 // into something meaningful.
2162 return ResolveAsTypeStep (ec
);
2168 if (e
is IMemberExpr
) {
2169 e
= MemberAccess
.ResolveMemberAccess (ec
, e
, null, loc
, this);
2173 IMemberExpr me
= e
as IMemberExpr
;
2177 // This fails if ResolveMemberAccess() was unable to decide whether
2178 // it's a field or a type of the same name.
2180 if (!me
.IsStatic
&& (me
.InstanceExpression
== null))
2184 TypeManager
.IsSubclassOrNestedChildOf (me
.InstanceExpression
.Type
, me
.DeclaringType
) &&
2185 me
.InstanceExpression
.Type
!= me
.DeclaringType
&&
2186 !me
.InstanceExpression
.Type
.IsSubclassOf (me
.DeclaringType
) &&
2187 (!intermediate
|| !MemberAccess
.IdenticalNameAndTypeName (ec
, this, e
, loc
))) {
2188 Error (38, "Cannot access nonstatic member `" + me
.Name
+ "' of " +
2189 "outer type `" + me
.DeclaringType
+ "' via nested type `" +
2190 me
.InstanceExpression
.Type
+ "'");
2194 return (right_side
!= null)
2195 ? e
.DoResolveLValue (ec
, right_side
)
2199 if (ec
.IsStatic
|| ec
.IsFieldInitializer
){
2203 return MemberStaticCheck (ec
, e
);
2208 public override void Emit (EmitContext ec
)
2211 // If this is ever reached, then we failed to
2212 // find the name as a namespace
2215 Error (103, "The name `" + Name
+
2216 "' does not exist in the class `" +
2217 ec
.DeclSpace
.Name
+ "'");
2220 public override string ToString ()
2227 /// Fully resolved expression that evaluates to a type
2229 public abstract class TypeExpr
: Expression
{
2230 override public Expression
ResolveAsTypeStep (EmitContext ec
)
2232 TypeExpr t
= DoResolveAsTypeStep (ec
);
2236 eclass
= ExprClass
.Type
;
2240 override public Expression
DoResolve (EmitContext ec
)
2242 return ResolveAsTypeTerminal (ec
, false);
2245 override public void Emit (EmitContext ec
)
2247 throw new Exception ("Should never be called");
2250 public virtual bool CheckAccessLevel (DeclSpace ds
)
2252 return ds
.CheckAccessLevel (Type
);
2255 public virtual bool AsAccessible (DeclSpace ds
, int flags
)
2257 return ds
.AsAccessible (Type
, flags
);
2260 public virtual bool IsClass
{
2261 get { return Type.IsClass; }
2264 public virtual bool IsValueType
{
2265 get { return Type.IsValueType; }
2268 public virtual bool IsInterface
{
2269 get { return Type.IsInterface; }
2272 public virtual bool IsSealed
{
2273 get { return Type.IsSealed; }
2276 public virtual bool CanInheritFrom ()
2278 if (Type
== TypeManager
.enum_type
||
2279 (Type
== TypeManager
.value_type
&& RootContext
.StdLib
) ||
2280 Type
== TypeManager
.multicast_delegate_type
||
2281 Type
== TypeManager
.delegate_type
||
2282 Type
== TypeManager
.array_type
)
2288 public virtual bool IsAttribute
{
2290 return Type
== TypeManager
.attribute_type
||
2291 Type
.IsSubclassOf (TypeManager
.attribute_type
);
2295 public virtual TypeExpr
[] GetInterfaces ()
2297 return TypeManager
.GetInterfaces (Type
);
2300 public abstract TypeExpr
DoResolveAsTypeStep (EmitContext ec
);
2302 public virtual Type
ResolveType (EmitContext ec
)
2304 TypeExpr t
= ResolveAsTypeTerminal (ec
, false);
2311 public abstract string Name
{
2315 public override bool Equals (object obj
)
2317 TypeExpr tobj
= obj
as TypeExpr
;
2321 return Type
== tobj
.Type
;
2324 public override int GetHashCode ()
2326 return Type
.GetHashCode ();
2329 public override string ToString ()
2335 public class TypeExpression
: TypeExpr
{
2336 public TypeExpression (Type t
, Location l
)
2339 eclass
= ExprClass
.Type
;
2343 public override TypeExpr
DoResolveAsTypeStep (EmitContext ec
)
2348 public override string Name
{
2350 return Type
.ToString ();
2356 /// Used to create types from a fully qualified name. These are just used
2357 /// by the parser to setup the core types. A TypeLookupExpression is always
2358 /// classified as a type.
2360 public class TypeLookupExpression
: TypeExpr
{
2363 public TypeLookupExpression (string name
)
2368 public override TypeExpr
DoResolveAsTypeStep (EmitContext ec
)
2371 type
= RootContext
.LookupType (ec
.DeclSpace
, name
, false, Location
.Null
);
2375 public override string Name
{
2383 /// MethodGroup Expression.
2385 /// This is a fully resolved expression that evaluates to a type
2387 public class MethodGroupExpr
: Expression
, IMemberExpr
{
2388 public MethodBase
[] Methods
;
2389 Expression instance_expression
= null;
2390 bool is_explicit_impl
= false;
2391 bool identical_type_name
= false;
2394 public MethodGroupExpr (MemberInfo
[] mi
, Location l
)
2396 Methods
= new MethodBase
[mi
.Length
];
2397 mi
.CopyTo (Methods
, 0);
2398 eclass
= ExprClass
.MethodGroup
;
2399 type
= TypeManager
.object_type
;
2403 public MethodGroupExpr (ArrayList list
, Location l
)
2405 Methods
= new MethodBase
[list
.Count
];
2408 list
.CopyTo (Methods
, 0);
2410 foreach (MemberInfo m
in list
){
2411 if (!(m
is MethodBase
)){
2412 Console
.WriteLine ("Name " + m
.Name
);
2413 Console
.WriteLine ("Found a: " + m
.GetType ().FullName
);
2420 eclass
= ExprClass
.MethodGroup
;
2421 type
= TypeManager
.object_type
;
2424 public Type DeclaringType
{
2427 // The methods are arranged in this order:
2428 // derived type -> base type
2430 return Methods
[0].DeclaringType
;
2435 // `A method group may have associated an instance expression'
2437 public Expression InstanceExpression
{
2439 return instance_expression
;
2443 instance_expression
= value;
2447 public bool IsExplicitImpl
{
2449 return is_explicit_impl
;
2453 is_explicit_impl
= value;
2457 public bool IdenticalTypeName
{
2459 return identical_type_name
;
2463 identical_type_name
= value;
2467 public bool IsBase
{
2476 public string Name
{
2478 return Methods
[0].Name
;
2482 public bool IsInstance
{
2484 foreach (MethodBase mb
in Methods
)
2492 public bool IsStatic
{
2494 foreach (MethodBase mb
in Methods
)
2502 override public Expression
DoResolve (EmitContext ec
)
2505 instance_expression
= null;
2507 if (instance_expression
!= null) {
2508 instance_expression
= instance_expression
.DoResolve (ec
);
2509 if (instance_expression
== null)
2516 public void ReportUsageError ()
2518 Report
.Error (654, loc
, "Method `" + DeclaringType
+ "." +
2519 Name
+ "()' is referenced without parentheses");
2522 override public void Emit (EmitContext ec
)
2524 ReportUsageError ();
2527 bool RemoveMethods (bool keep_static
)
2529 ArrayList smethods
= new ArrayList ();
2531 foreach (MethodBase mb
in Methods
){
2532 if (mb
.IsStatic
== keep_static
)
2536 if (smethods
.Count
== 0)
2539 Methods
= new MethodBase
[smethods
.Count
];
2540 smethods
.CopyTo (Methods
, 0);
2546 /// Removes any instance methods from the MethodGroup, returns
2547 /// false if the resulting set is empty.
2549 public bool RemoveInstanceMethods ()
2551 return RemoveMethods (true);
2555 /// Removes any static methods from the MethodGroup, returns
2556 /// false if the resulting set is empty.
2558 public bool RemoveStaticMethods ()
2560 return RemoveMethods (false);
2565 /// Fully resolved expression that evaluates to a Field
2567 public class FieldExpr
: Expression
, IAssignMethod
, IMemoryLocation
, IMemberExpr
, IVariable
{
2568 public readonly FieldInfo FieldInfo
;
2569 Expression instance_expr
;
2570 VariableInfo variable_info
;
2572 LocalTemporary temp
;
2575 public FieldExpr (FieldInfo fi
, Location l
)
2578 eclass
= ExprClass
.Variable
;
2579 type
= fi
.FieldType
;
2583 public string Name
{
2585 return FieldInfo
.Name
;
2589 public bool IsInstance
{
2591 return !FieldInfo
.IsStatic
;
2595 public bool IsStatic
{
2597 return FieldInfo
.IsStatic
;
2601 public Type DeclaringType
{
2603 return FieldInfo
.DeclaringType
;
2607 public Expression InstanceExpression
{
2609 return instance_expr
;
2613 instance_expr
= value;
2617 public VariableInfo VariableInfo
{
2619 return variable_info
;
2623 override public Expression
DoResolve (EmitContext ec
)
2625 if (!FieldInfo
.IsStatic
){
2626 if (instance_expr
== null){
2628 // This can happen when referencing an instance field using
2629 // a fully qualified type expression: TypeName.InstanceField = xxx
2631 SimpleName
.Error_ObjectRefRequired (ec
, loc
, FieldInfo
.Name
);
2635 // Resolve the field's instance expression while flow analysis is turned
2636 // off: when accessing a field "a.b", we must check whether the field
2637 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2638 instance_expr
= instance_expr
.Resolve (ec
, ResolveFlags
.VariableOrValue
|
2639 ResolveFlags
.DisableFlowAnalysis
);
2640 if (instance_expr
== null)
2644 ObsoleteAttribute oa
;
2645 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2647 oa
= f
.GetObsoleteAttribute (f
.Parent
);
2649 AttributeTester
.Report_ObsoleteMessage (oa
, f
.GetSignatureForError (), loc
);
2651 // To be sure that type is external because we do not register generated fields
2652 } else if (!(FieldInfo
.DeclaringType
is TypeBuilder
)) {
2653 oa
= AttributeTester
.GetMemberObsoleteAttribute (FieldInfo
);
2655 AttributeTester
.Report_ObsoleteMessage (oa
, TypeManager
.GetFullNameSignature (FieldInfo
), loc
);
2658 if (ec
.CurrentAnonymousMethod
!= null){
2659 if (!FieldInfo
.IsStatic
){
2660 if (ec
.TypeContainer
is Struct
){
2661 Report
.Error (1673, loc
, "Can not reference instance variables in anonymous methods hosted in structs");
2664 ec
.CaptureField (this);
2668 // If the instance expression is a local variable or parameter.
2669 IVariable
var = instance_expr
as IVariable
;
2670 if ((var == null) || (var.VariableInfo
== null))
2673 VariableInfo vi
= var.VariableInfo
;
2674 if (!vi
.IsFieldAssigned (ec
, FieldInfo
.Name
, loc
))
2677 variable_info
= vi
.GetSubStruct (FieldInfo
.Name
);
2681 void Report_AssignToReadonly (bool is_instance
)
2686 msg
= "Readonly field can not be assigned outside " +
2687 "of constructor or variable initializer";
2689 msg
= "A static readonly field can only be assigned in " +
2690 "a static constructor";
2692 Report
.Error (is_instance
? 191 : 198, loc
, msg
);
2695 override public Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
2697 IVariable
var = instance_expr
as IVariable
;
2698 if ((var != null) && (var.VariableInfo
!= null))
2699 var.VariableInfo
.SetFieldAssigned (ec
, FieldInfo
.Name
);
2701 Expression e
= DoResolve (ec
);
2706 if (!FieldInfo
.IsStatic
&& (instance_expr
.Type
.IsValueType
&& !(instance_expr
is IMemoryLocation
))) {
2707 // FIXME: Provide better error reporting.
2708 Error (1612, "Cannot modify expression because it is not a variable.");
2712 if (!FieldInfo
.IsInitOnly
)
2715 FieldBase fb
= TypeManager
.GetField (FieldInfo
);
2720 // InitOnly fields can only be assigned in constructors
2723 if (ec
.IsConstructor
){
2724 if (IsStatic
&& !ec
.IsStatic
)
2725 Report_AssignToReadonly (false);
2727 if (ec
.ContainerType
== FieldInfo
.DeclaringType
)
2731 Report_AssignToReadonly (!IsStatic
);
2736 public bool VerifyFixed (bool is_expression
)
2738 IVariable variable
= instance_expr
as IVariable
;
2739 if ((variable
== null) || !variable
.VerifyFixed (true))
2745 public void Emit (EmitContext ec
, bool leave_copy
)
2747 ILGenerator ig
= ec
.ig
;
2748 bool is_volatile
= false;
2750 if (FieldInfo
is FieldBuilder
){
2751 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2753 if ((f
.ModFlags
& Modifiers
.VOLATILE
) != 0)
2756 f
.status
|= Field
.Status
.USED
;
2760 if (FieldInfo
.IsStatic
){
2762 ig
.Emit (OpCodes
.Volatile
);
2764 ig
.Emit (OpCodes
.Ldsfld
, FieldInfo
);
2770 ig
.Emit (OpCodes
.Volatile
);
2772 ig
.Emit (OpCodes
.Ldfld
, FieldInfo
);
2776 ec
.ig
.Emit (OpCodes
.Dup
);
2777 if (!FieldInfo
.IsStatic
) {
2778 temp
= new LocalTemporary (ec
, this.Type
);
2784 public void EmitAssign (EmitContext ec
, Expression source
, bool leave_copy
, bool prepare_for_load
)
2786 FieldAttributes fa
= FieldInfo
.Attributes
;
2787 bool is_static
= (fa
& FieldAttributes
.Static
) != 0;
2788 bool is_readonly
= (fa
& FieldAttributes
.InitOnly
) != 0;
2789 ILGenerator ig
= ec
.ig
;
2790 prepared
= prepare_for_load
;
2792 if (is_readonly
&& !ec
.IsConstructor
){
2793 Report_AssignToReadonly (!is_static
);
2799 if (prepare_for_load
)
2800 ig
.Emit (OpCodes
.Dup
);
2805 ec
.ig
.Emit (OpCodes
.Dup
);
2806 if (!FieldInfo
.IsStatic
) {
2807 temp
= new LocalTemporary (ec
, this.Type
);
2812 if (FieldInfo
is FieldBuilder
){
2813 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2815 if ((f
.ModFlags
& Modifiers
.VOLATILE
) != 0)
2816 ig
.Emit (OpCodes
.Volatile
);
2818 f
.status
|= Field
.Status
.ASSIGNED
;
2823 ig
.Emit (OpCodes
.Stsfld
, FieldInfo
);
2825 ig
.Emit (OpCodes
.Stfld
, FieldInfo
);
2831 void EmitInstance (EmitContext ec
)
2833 if (instance_expr
.Type
.IsValueType
) {
2834 if (instance_expr
is IMemoryLocation
) {
2835 ((IMemoryLocation
) instance_expr
).AddressOf (ec
, AddressOp
.LoadStore
);
2837 LocalTemporary t
= new LocalTemporary (ec
, instance_expr
.Type
);
2838 instance_expr
.Emit (ec
);
2840 t
.AddressOf (ec
, AddressOp
.Store
);
2843 instance_expr
.Emit (ec
);
2846 public override void Emit (EmitContext ec
)
2851 public void AddressOf (EmitContext ec
, AddressOp mode
)
2853 ILGenerator ig
= ec
.ig
;
2855 if (FieldInfo
is FieldBuilder
){
2856 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2858 if ((f
.ModFlags
& Modifiers
.VOLATILE
) != 0){
2859 Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
2863 if ((mode
& AddressOp
.Store
) != 0)
2864 f
.status
|= Field
.Status
.ASSIGNED
;
2865 if ((mode
& AddressOp
.Load
) != 0)
2866 f
.status
|= Field
.Status
.USED
;
2871 // Handle initonly fields specially: make a copy and then
2872 // get the address of the copy.
2875 if (FieldInfo
.IsInitOnly
){
2877 if (ec
.IsConstructor
){
2878 if (FieldInfo
.IsStatic
){
2890 local
= ig
.DeclareLocal (type
);
2891 ig
.Emit (OpCodes
.Stloc
, local
);
2892 ig
.Emit (OpCodes
.Ldloca
, local
);
2897 if (FieldInfo
.IsStatic
){
2898 ig
.Emit (OpCodes
.Ldsflda
, FieldInfo
);
2901 ig
.Emit (OpCodes
.Ldflda
, FieldInfo
);
2907 // A FieldExpr whose address can not be taken
2909 public class FieldExprNoAddress
: FieldExpr
, IMemoryLocation
{
2910 public FieldExprNoAddress (FieldInfo fi
, Location loc
) : base (fi
, loc
)
2914 public new void AddressOf (EmitContext ec
, AddressOp mode
)
2916 Report
.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
2921 /// Expression that evaluates to a Property. The Assign class
2922 /// might set the `Value' expression if we are in an assignment.
2924 /// This is not an LValue because we need to re-write the expression, we
2925 /// can not take data from the stack and store it.
2927 public class PropertyExpr
: ExpressionStatement
, IAssignMethod
, IMemberExpr
{
2928 public readonly PropertyInfo PropertyInfo
;
2931 // This is set externally by the `BaseAccess' class
2934 MethodInfo getter
, setter
;
2936 bool must_do_cs1540_check
;
2938 Expression instance_expr
;
2939 LocalTemporary temp
;
2942 public PropertyExpr (EmitContext ec
, PropertyInfo pi
, Location l
)
2945 eclass
= ExprClass
.PropertyAccess
;
2949 type
= TypeManager
.TypeToCoreType (pi
.PropertyType
);
2951 ResolveAccessors (ec
);
2954 public string Name
{
2956 return PropertyInfo
.Name
;
2960 public bool IsInstance
{
2966 public bool IsStatic
{
2972 public Type DeclaringType
{
2974 return PropertyInfo
.DeclaringType
;
2979 // The instance expression associated with this expression
2981 public Expression InstanceExpression
{
2983 instance_expr
= value;
2987 return instance_expr
;
2991 public bool VerifyAssignable ()
2993 if (setter
== null) {
2994 Report
.Error (200, loc
,
2995 "The property `" + PropertyInfo
.Name
+
2996 "' can not be assigned to, as it has not set accessor");
3003 void FindAccessors (Type invocation_type
)
3005 BindingFlags flags
= BindingFlags
.Public
| BindingFlags
.NonPublic
|
3006 BindingFlags
.Static
| BindingFlags
.Instance
|
3007 BindingFlags
.DeclaredOnly
;
3009 Type current
= PropertyInfo
.DeclaringType
;
3010 for (; current
!= null; current
= current
.BaseType
) {
3011 MemberInfo
[] group = TypeManager
.MemberLookup (
3012 invocation_type
, invocation_type
, current
,
3013 MemberTypes
.Property
, flags
, PropertyInfo
.Name
, null);
3018 if (group.Length
!= 1)
3019 // Oooops, can this ever happen ?
3022 PropertyInfo pi
= (PropertyInfo
) group [0];
3025 getter
= pi
.GetGetMethod (true);;
3028 setter
= pi
.GetSetMethod (true);;
3030 MethodInfo accessor
= getter
!= null ? getter
: setter
;
3032 if (!accessor
.IsVirtual
)
3037 bool IsAccessorAccessible (Type invocation_type
, MethodInfo mi
)
3039 MethodAttributes ma
= mi
.Attributes
& MethodAttributes
.MemberAccessMask
;
3042 // If only accessible to the current class or children
3044 if (ma
== MethodAttributes
.Private
) {
3045 Type declaring_type
= mi
.DeclaringType
;
3047 if (invocation_type
!= declaring_type
)
3048 return TypeManager
.IsSubclassOrNestedChildOf (invocation_type
, declaring_type
);
3053 // FamAndAssem requires that we not only derivate, but we are on the
3056 if (ma
== MethodAttributes
.FamANDAssem
){
3057 return (mi
.DeclaringType
.Assembly
!= invocation_type
.Assembly
);
3060 // Assembly and FamORAssem succeed if we're in the same assembly.
3061 if ((ma
== MethodAttributes
.Assembly
) || (ma
== MethodAttributes
.FamORAssem
)){
3062 if (mi
.DeclaringType
.Assembly
== invocation_type
.Assembly
)
3066 // We already know that we aren't in the same assembly.
3067 if (ma
== MethodAttributes
.Assembly
)
3070 // Family and FamANDAssem require that we derive.
3071 if ((ma
== MethodAttributes
.Family
) || (ma
== MethodAttributes
.FamANDAssem
) || (ma
== MethodAttributes
.FamORAssem
)){
3072 if (!TypeManager
.IsSubclassOrNestedChildOf (invocation_type
, mi
.DeclaringType
))
3075 if (!TypeManager
.IsNestedChildOf (invocation_type
, mi
.DeclaringType
))
3076 must_do_cs1540_check
= true;
3085 // We also perform the permission checking here, as the PropertyInfo does not
3086 // hold the information for the accessibility of its setter/getter
3088 void ResolveAccessors (EmitContext ec
)
3090 FindAccessors (ec
.ContainerType
);
3092 is_static
= getter
!= null ? getter
.IsStatic
: setter
.IsStatic
;
3095 bool InstanceResolve (EmitContext ec
)
3097 if ((instance_expr
== null) && ec
.IsStatic
&& !is_static
) {
3098 SimpleName
.Error_ObjectRefRequired (ec
, loc
, PropertyInfo
.Name
);
3102 if (instance_expr
!= null) {
3103 instance_expr
= instance_expr
.DoResolve (ec
);
3104 if (instance_expr
== null)
3108 if (must_do_cs1540_check
&& (instance_expr
!= null)) {
3109 if ((instance_expr
.Type
!= ec
.ContainerType
) &&
3110 ec
.ContainerType
.IsSubclassOf (instance_expr
.Type
)) {
3111 Report
.Error (1540, loc
, "Cannot access protected member `" +
3112 PropertyInfo
.DeclaringType
+ "." + PropertyInfo
.Name
+
3113 "' via a qualifier of type `" +
3114 TypeManager
.CSharpName (instance_expr
.Type
) +
3115 "'; the qualifier must be of type `" +
3116 TypeManager
.CSharpName (ec
.ContainerType
) +
3117 "' (or derived from it)");
3125 override public Expression
DoResolve (EmitContext ec
)
3127 if (getter
!= null){
3128 if (TypeManager
.GetArgumentTypes (getter
).Length
!= 0){
3130 117, loc
, "`{0}' does not contain a " +
3131 "definition for `{1}'.", getter
.DeclaringType
,
3137 if (getter
== null){
3139 // The following condition happens if the PropertyExpr was
3140 // created, but is invalid (ie, the property is inaccessible),
3141 // and we did not want to embed the knowledge about this in
3142 // the caller routine. This only avoids double error reporting.
3147 Report
.Error (154, loc
,
3148 "The property `" + PropertyInfo
.Name
+
3149 "' can not be used in " +
3150 "this context because it lacks a get accessor");
3154 if (!IsAccessorAccessible (ec
.ContainerType
, getter
)) {
3155 Report
.Error (122, loc
, "'{0}.get' is inaccessible due to its protection level", PropertyInfo
.Name
);
3159 if (!InstanceResolve (ec
))
3163 // Only base will allow this invocation to happen.
3165 if (IsBase
&& getter
.IsAbstract
){
3166 Report
.Error (205, loc
, "Cannot call an abstract base property: " +
3167 PropertyInfo
.DeclaringType
+ "." +PropertyInfo
.Name
);
3174 override public Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
3176 if (setter
== null){
3178 // The following condition happens if the PropertyExpr was
3179 // created, but is invalid (ie, the property is inaccessible),
3180 // and we did not want to embed the knowledge about this in
3181 // the caller routine. This only avoids double error reporting.
3186 Report
.Error (154, loc
,
3187 "The property `" + PropertyInfo
.Name
+
3188 "' can not be used in " +
3189 "this context because it lacks a set accessor");
3193 if (TypeManager
.GetArgumentTypes (setter
).Length
!= 1){
3195 117, loc
, "`{0}' does not contain a " +
3196 "definition for `{1}'.", getter
.DeclaringType
,
3201 if (!IsAccessorAccessible (ec
.ContainerType
, setter
)) {
3202 Report
.Error (122, loc
, "'{0}.set' is inaccessible due to its protection level", PropertyInfo
.Name
);
3206 if (!InstanceResolve (ec
))
3210 // Only base will allow this invocation to happen.
3212 if (IsBase
&& setter
.IsAbstract
){
3213 Report
.Error (205, loc
, "Cannot call an abstract base property: " +
3214 PropertyInfo
.DeclaringType
+ "." +PropertyInfo
.Name
);
3219 // Check that we are not making changes to a temporary memory location
3221 if (instance_expr
!= null && instance_expr
.Type
.IsValueType
&& !(instance_expr
is IMemoryLocation
)) {
3222 // FIXME: Provide better error reporting.
3223 Error (1612, "Cannot modify expression because it is not a variable.");
3232 public override void Emit (EmitContext ec
)
3237 void EmitInstance (EmitContext ec
)
3242 if (instance_expr
.Type
.IsValueType
) {
3243 if (instance_expr
is IMemoryLocation
) {
3244 ((IMemoryLocation
) instance_expr
).AddressOf (ec
, AddressOp
.LoadStore
);
3246 LocalTemporary t
= new LocalTemporary (ec
, instance_expr
.Type
);
3247 instance_expr
.Emit (ec
);
3249 t
.AddressOf (ec
, AddressOp
.Store
);
3252 instance_expr
.Emit (ec
);
3255 ec
.ig
.Emit (OpCodes
.Dup
);
3259 public void Emit (EmitContext ec
, bool leave_copy
)
3265 // Special case: length of single dimension array property is turned into ldlen
3267 if ((getter
== TypeManager
.system_int_array_get_length
) ||
3268 (getter
== TypeManager
.int_array_get_length
)){
3269 Type iet
= instance_expr
.Type
;
3272 // System.Array.Length can be called, but the Type does not
3273 // support invoking GetArrayRank, so test for that case first
3275 if (iet
!= TypeManager
.array_type
&& (iet
.GetArrayRank () == 1)) {
3276 ec
.ig
.Emit (OpCodes
.Ldlen
);
3277 ec
.ig
.Emit (OpCodes
.Conv_I4
);
3282 Invocation
.EmitCall (ec
, IsBase
, IsStatic
, new EmptyAddressOf (), getter
, null, loc
);
3287 ec
.ig
.Emit (OpCodes
.Dup
);
3289 temp
= new LocalTemporary (ec
, this.Type
);
3295 // Implements the IAssignMethod interface for assignments
3297 public void EmitAssign (EmitContext ec
, Expression source
, bool leave_copy
, bool prepare_for_load
)
3299 prepared
= prepare_for_load
;
3305 ec
.ig
.Emit (OpCodes
.Dup
);
3307 temp
= new LocalTemporary (ec
, this.Type
);
3312 ArrayList args
= new ArrayList (1);
3313 args
.Add (new Argument (new EmptyAddressOf (), Argument
.AType
.Expression
));
3315 Invocation
.EmitCall (ec
, IsBase
, IsStatic
, new EmptyAddressOf (), setter
, args
, loc
);
3321 override public void EmitStatement (EmitContext ec
)
3324 ec
.ig
.Emit (OpCodes
.Pop
);
3329 /// Fully resolved expression that evaluates to an Event
3331 public class EventExpr
: Expression
, IMemberExpr
{
3332 public readonly EventInfo EventInfo
;
3333 Expression instance_expr
;
3336 MethodInfo add_accessor
, remove_accessor
;
3338 public EventExpr (EventInfo ei
, Location loc
)
3342 eclass
= ExprClass
.EventAccess
;
3344 add_accessor
= TypeManager
.GetAddMethod (ei
);
3345 remove_accessor
= TypeManager
.GetRemoveMethod (ei
);
3347 if (add_accessor
.IsStatic
|| remove_accessor
.IsStatic
)
3350 if (EventInfo
is MyEventBuilder
){
3351 MyEventBuilder eb
= (MyEventBuilder
) EventInfo
;
3352 type
= eb
.EventType
;
3355 type
= EventInfo
.EventHandlerType
;
3358 public string Name
{
3360 return EventInfo
.Name
;
3364 public bool IsInstance
{
3370 public bool IsStatic
{
3376 public Type DeclaringType
{
3378 return EventInfo
.DeclaringType
;
3382 public Expression InstanceExpression
{
3384 return instance_expr
;
3388 instance_expr
= value;
3392 public override Expression
DoResolve (EmitContext ec
)
3394 if (instance_expr
!= null) {
3395 instance_expr
= instance_expr
.DoResolve (ec
);
3396 if (instance_expr
== null)
3404 public override void Emit (EmitContext ec
)
3406 Report
.Error (70, loc
, "The event `" + Name
+ "' can only appear on the left hand side of += or -= (except on the defining type)");
3409 public void EmitAddOrRemove (EmitContext ec
, Expression source
)
3411 BinaryDelegate source_del
= (BinaryDelegate
) source
;
3412 Expression handler
= source_del
.Right
;
3414 Argument arg
= new Argument (handler
, Argument
.AType
.Expression
);
3415 ArrayList args
= new ArrayList ();
3419 if (source_del
.IsAddition
)
3420 Invocation
.EmitCall (
3421 ec
, false, IsStatic
, instance_expr
, add_accessor
, args
, loc
);
3423 Invocation
.EmitCall (
3424 ec
, false, IsStatic
, instance_expr
, remove_accessor
, args
, loc
);