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 // Mask of all the expression class flags.
57 // Disable control flow analysis while resolving the expression.
58 // This is used when resolving the instance expression of a field expression.
59 DisableFlowAnalysis
= 8,
61 // Set if this is resolving the first part of a MemberAccess.
64 // Disable control flow analysis _of struct_ while resolving the expression.
65 // This is used when resolving the instance expression of a field expression.
66 DisableStructFlowAnalysis
= 32,
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
{
110 /// Base class for expressions
112 public abstract class Expression
{
113 public ExprClass eclass
;
115 protected Location loc
;
119 set { type = value; }
122 public virtual Location Location
{
127 /// Utility wrapper routine for Error, just to beautify the code
129 public void Error (int error
, string s
)
132 Report
.Error (error
, s
);
134 Report
.Error (error
, loc
, s
);
137 // Not nice but we have broken hierarchy
138 public virtual void CheckMarshallByRefAccess (Type container
) {}
140 public virtual string GetSignatureForError ()
142 return TypeManager
.CSharpName (type
);
145 public static bool IsAccessorAccessible (Type invocation_type
, MethodInfo mi
, out bool must_do_cs1540_check
)
147 MethodAttributes ma
= mi
.Attributes
& MethodAttributes
.MemberAccessMask
;
149 must_do_cs1540_check
= false; // by default we do not check for this
152 // If only accessible to the current class or children
154 if (ma
== MethodAttributes
.Private
)
155 return invocation_type
== mi
.DeclaringType
||
156 TypeManager
.IsNestedChildOf (invocation_type
, mi
.DeclaringType
);
158 if (mi
.DeclaringType
.Assembly
== invocation_type
.Assembly
) {
159 if (ma
== MethodAttributes
.Assembly
|| ma
== MethodAttributes
.FamORAssem
)
162 if (ma
== MethodAttributes
.Assembly
|| ma
== MethodAttributes
.FamANDAssem
)
166 // Family and FamANDAssem require that we derive.
167 // FamORAssem requires that we derive if in different assemblies.
168 if (ma
== MethodAttributes
.Family
||
169 ma
== MethodAttributes
.FamANDAssem
||
170 ma
== MethodAttributes
.FamORAssem
) {
171 if (!TypeManager
.IsNestedFamilyAccessible (invocation_type
, mi
.DeclaringType
))
174 if (!TypeManager
.IsNestedChildOf (invocation_type
, mi
.DeclaringType
))
175 must_do_cs1540_check
= true;
184 /// Performs semantic analysis on the Expression
188 /// The Resolve method is invoked to perform the semantic analysis
191 /// The return value is an expression (it can be the
192 /// same expression in some cases) or a new
193 /// expression that better represents this node.
195 /// For example, optimizations of Unary (LiteralInt)
196 /// would return a new LiteralInt with a negated
199 /// If there is an error during semantic analysis,
200 /// then an error should be reported (using Report)
201 /// and a null value should be returned.
203 /// There are two side effects expected from calling
204 /// Resolve(): the the field variable "eclass" should
205 /// be set to any value of the enumeration
206 /// `ExprClass' and the type variable should be set
207 /// to a valid type (this is the type of the
210 public abstract Expression
DoResolve (EmitContext ec
);
212 public virtual Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
218 // This is used if the expression should be resolved as a type or namespace name.
219 // the default implementation fails.
221 public virtual FullNamedExpression
ResolveAsTypeStep (EmitContext ec
, bool silent
)
227 // This is used to resolve the expression as a type, a null
228 // value will be returned if the expression is not a type
231 public TypeExpr
ResolveAsTypeTerminal (EmitContext ec
, bool silent
)
233 int errors
= Report
.Errors
;
235 FullNamedExpression fne
= ResolveAsTypeStep (ec
, silent
);
240 if (fne
.eclass
!= ExprClass
.Type
) {
241 if (!silent
&& errors
== Report
.Errors
)
242 fne
.Error_UnexpectedKind (null, "type", loc
);
246 TypeExpr te
= fne
as TypeExpr
;
248 if (!te
.CheckAccessLevel (ec
.DeclSpace
)) {
249 ErrorIsInaccesible (loc
, TypeManager
.CSharpName (te
.Type
));
257 public static void ErrorIsInaccesible (Location loc
, string name
)
259 Report
.Error (122, loc
, "`{0}' is inaccessible due to its protection level", name
);
262 protected static void Error_CannotAccessProtected (Location loc
, MemberInfo m
, Type qualifier
, Type container
)
264 Report
.Error (1540, loc
, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
265 + " the qualifier must be of type `{2}' (or derived from it)",
266 TypeManager
.GetFullNameSignature (m
),
267 TypeManager
.CSharpName (qualifier
),
268 TypeManager
.CSharpName (container
));
272 public virtual void Error_ValueCannotBeConverted (Location loc
, Type target
, bool expl
)
274 if (Type
.Name
== target
.Name
){
275 Report
.ExtraInformation (loc
,
277 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
278 Type
.Name
, Type
.Assembly
.FullName
, target
.Assembly
.FullName
));
283 Report
.Error (30, loc
, "Cannot convert type `{0}' to `{1}'",
284 GetSignatureForError (), TypeManager
.CSharpName (target
));
288 Expression e
= (this is EnumConstant
) ? ((EnumConstant
)this).Child
: this;
289 bool b
= Convert
.ExplicitNumericConversion (e
, target
) != null;
291 if (b
|| Convert
.ExplicitReferenceConversionExists (Type
, target
) || Convert
.ExplicitUnsafe (e
, target
) != null) {
292 Report
.Error (266, loc
, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
293 TypeManager
.CSharpName (Type
), TypeManager
.CSharpName (target
));
297 if (Type
!= TypeManager
.string_type
&& this is Constant
&& !(this is NullCast
)) {
298 Report
.Error (31, loc
, "Constant value `{0}' cannot be converted to a `{1}'",
299 GetSignatureForError (), TypeManager
.CSharpName (target
));
303 Report
.Error (29, loc
, "Cannot implicitly convert type {0} to `{1}'",
304 Type
== TypeManager
.anonymous_method_type
?
305 "anonymous method" : "`" + GetSignatureForError () + "'",
306 TypeManager
.CSharpName (target
));
309 protected static void Error_TypeDoesNotContainDefinition (Location loc
, Type type
, string name
)
311 Report
.Error (117, loc
, "`{0}' does not contain a definition for `{1}'",
312 TypeManager
.CSharpName (type
), name
);
315 ResolveFlags
ExprClassToResolveFlags ()
319 case ExprClass
.Namespace
:
320 return ResolveFlags
.Type
;
322 case ExprClass
.MethodGroup
:
323 return ResolveFlags
.MethodGroup
;
325 case ExprClass
.Value
:
326 case ExprClass
.Variable
:
327 case ExprClass
.PropertyAccess
:
328 case ExprClass
.EventAccess
:
329 case ExprClass
.IndexerAccess
:
330 return ResolveFlags
.VariableOrValue
;
333 throw new Exception ("Expression " + GetType () +
334 " ExprClass is Invalid after resolve");
340 /// Resolves an expression and performs semantic analysis on it.
344 /// Currently Resolve wraps DoResolve to perform sanity
345 /// checking and assertion checking on what we expect from Resolve.
347 public Expression
Resolve (EmitContext ec
, ResolveFlags flags
)
349 if ((flags
& ResolveFlags
.MaskExprClass
) == ResolveFlags
.Type
)
350 return ResolveAsTypeStep (ec
, false);
352 bool old_do_flow_analysis
= ec
.DoFlowAnalysis
;
353 bool old_omit_struct_analysis
= ec
.OmitStructFlowAnalysis
;
354 if ((flags
& ResolveFlags
.DisableFlowAnalysis
) != 0)
355 ec
.DoFlowAnalysis
= false;
356 if ((flags
& ResolveFlags
.DisableStructFlowAnalysis
) != 0)
357 ec
.OmitStructFlowAnalysis
= true;
360 bool intermediate
= (flags
& ResolveFlags
.Intermediate
) == ResolveFlags
.Intermediate
;
361 if (this is SimpleName
)
362 e
= ((SimpleName
) this).DoResolve (ec
, intermediate
);
367 ec
.DoFlowAnalysis
= old_do_flow_analysis
;
368 ec
.OmitStructFlowAnalysis
= old_omit_struct_analysis
;
373 if ((flags
& e
.ExprClassToResolveFlags ()) == 0) {
374 e
.Error_UnexpectedKind (flags
, loc
);
378 if (e
.type
== null && !(e
is Namespace
)) {
379 throw new Exception (
380 "Expression " + e
.GetType () +
381 " did not set its type after Resolve\n" +
382 "called from: " + this.GetType ());
389 /// Resolves an expression and performs semantic analysis on it.
391 public Expression
Resolve (EmitContext ec
)
393 Expression e
= Resolve (ec
, ResolveFlags
.VariableOrValue
| ResolveFlags
.MethodGroup
);
395 if (e
!= null && e
.eclass
== ExprClass
.MethodGroup
&& RootContext
.Version
== LanguageVersion
.ISO_1
) {
396 ((MethodGroupExpr
) e
).ReportUsageError ();
402 public Constant
ResolveAsConstant (EmitContext ec
, MemberCore mc
)
404 Expression e
= Resolve (ec
);
408 Constant c
= e
as Constant
;
412 EmptyCast empty
= e
as EmptyCast
;
414 c
= empty
.Child
as Constant
;
416 // TODO: not sure about this maybe there is easier way how to use EmptyCast
423 Const
.Error_ExpressionMustBeConstant (loc
, mc
.GetSignatureForError ());
428 /// Resolves an expression for LValue assignment
432 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
433 /// checking and assertion checking on what we expect from Resolve
435 public Expression
ResolveLValue (EmitContext ec
, Expression right_side
, Location loc
)
437 int errors
= Report
.Errors
;
438 Expression e
= DoResolveLValue (ec
, right_side
);
441 if (errors
== Report
.Errors
)
442 Report
.Error (131, loc
, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
447 if (e
.eclass
== ExprClass
.Invalid
)
448 throw new Exception ("Expression " + e
+
449 " ExprClass is Invalid after resolve");
451 if (e
.eclass
== ExprClass
.MethodGroup
) {
452 ((MethodGroupExpr
) e
).ReportUsageError ();
457 throw new Exception ("Expression " + e
+
458 " did not set its type after Resolve");
465 /// Emits the code for the expression
469 /// The Emit method is invoked to generate the code
470 /// for the expression.
472 public abstract void Emit (EmitContext ec
);
474 public virtual void EmitBranchable (EmitContext ec
, Label target
, bool onTrue
)
477 ec
.ig
.Emit (onTrue
? OpCodes
.Brtrue
: OpCodes
.Brfalse
, target
);
481 /// Protected constructor. Only derivate types should
482 /// be able to be created
485 protected Expression ()
487 eclass
= ExprClass
.Invalid
;
492 /// Returns a literalized version of a literal FieldInfo
496 /// The possible return values are:
497 /// IntConstant, UIntConstant
498 /// LongLiteral, ULongConstant
499 /// FloatConstant, DoubleConstant
502 /// The value returned is already resolved.
504 public static Constant
Constantify (object v
, Type t
)
506 if (t
== TypeManager
.int32_type
)
507 return new IntConstant ((int) v
, Location
.Null
);
508 else if (t
== TypeManager
.uint32_type
)
509 return new UIntConstant ((uint) v
, Location
.Null
);
510 else if (t
== TypeManager
.int64_type
)
511 return new LongConstant ((long) v
, Location
.Null
);
512 else if (t
== TypeManager
.uint64_type
)
513 return new ULongConstant ((ulong) v
, Location
.Null
);
514 else if (t
== TypeManager
.float_type
)
515 return new FloatConstant ((float) v
, Location
.Null
);
516 else if (t
== TypeManager
.double_type
)
517 return new DoubleConstant ((double) v
, Location
.Null
);
518 else if (t
== TypeManager
.string_type
)
519 return new StringConstant ((string) v
, Location
.Null
);
520 else if (t
== TypeManager
.short_type
)
521 return new ShortConstant ((short)v
, Location
.Null
);
522 else if (t
== TypeManager
.ushort_type
)
523 return new UShortConstant ((ushort)v
, Location
.Null
);
524 else if (t
== TypeManager
.sbyte_type
)
525 return new SByteConstant ((sbyte)v
, Location
.Null
);
526 else if (t
== TypeManager
.byte_type
)
527 return new ByteConstant ((byte)v
, Location
.Null
);
528 else if (t
== TypeManager
.char_type
)
529 return new CharConstant ((char)v
, Location
.Null
);
530 else if (t
== TypeManager
.bool_type
)
531 return new BoolConstant ((bool) v
, Location
.Null
);
532 else if (t
== TypeManager
.decimal_type
)
533 return new DecimalConstant ((decimal) v
, Location
.Null
);
534 else if (TypeManager
.IsEnumType (t
)){
535 Type real_type
= TypeManager
.TypeToCoreType (v
.GetType ());
537 real_type
= System
.Enum
.GetUnderlyingType (real_type
);
539 Constant e
= Constantify (v
, real_type
);
541 return new EnumConstant (e
, t
);
542 } else if (v
== null && !TypeManager
.IsValueType (t
))
543 return new NullLiteral (Location
.Null
);
545 throw new Exception ("Unknown type for constant (" + t
+
550 /// Returns a fully formed expression after a MemberLookup
553 public static Expression
ExprClassFromMemberInfo (EmitContext ec
, MemberInfo mi
, Location loc
)
556 return new EventExpr ((EventInfo
) mi
, loc
);
557 else if (mi
is FieldInfo
)
558 return new FieldExpr ((FieldInfo
) mi
, loc
);
559 else if (mi
is PropertyInfo
)
560 return new PropertyExpr (ec
, (PropertyInfo
) mi
, loc
);
561 else if (mi
is Type
){
562 return new TypeExpression ((System
.Type
) mi
, loc
);
568 protected static ArrayList almostMatchedMembers
= new ArrayList (4);
571 // FIXME: Probably implement a cache for (t,name,current_access_set)?
573 // This code could use some optimizations, but we need to do some
574 // measurements. For example, we could use a delegate to `flag' when
575 // something can not any longer be a method-group (because it is something
579 // If the return value is an Array, then it is an array of
582 // If the return value is an MemberInfo, it is anything, but a Method
586 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
587 // the arguments here and have MemberLookup return only the methods that
588 // match the argument count/type, unlike we are doing now (we delay this
591 // This is so we can catch correctly attempts to invoke instance methods
592 // from a static body (scan for error 120 in ResolveSimpleName).
595 // FIXME: Potential optimization, have a static ArrayList
598 public static Expression
MemberLookup (EmitContext ec
, Type queried_type
, string name
,
599 MemberTypes mt
, BindingFlags bf
, Location loc
)
601 return MemberLookup (ec
, ec
.ContainerType
, null, queried_type
, name
, mt
, bf
, loc
);
605 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
606 // `qualifier_type' or null to lookup members in the current class.
609 public static Expression
MemberLookup (EmitContext ec
, Type container_type
,
610 Type qualifier_type
, Type queried_type
,
611 string name
, MemberTypes mt
,
612 BindingFlags bf
, Location loc
)
614 almostMatchedMembers
.Clear ();
616 MemberInfo
[] mi
= TypeManager
.MemberLookup (container_type
, qualifier_type
,
617 queried_type
, mt
, bf
, name
, almostMatchedMembers
);
622 int count
= mi
.Length
;
624 if (mi
[0] is MethodBase
)
625 return new MethodGroupExpr (mi
, loc
);
630 return ExprClassFromMemberInfo (ec
, mi
[0], loc
);
633 public const MemberTypes AllMemberTypes
=
634 MemberTypes
.Constructor
|
638 MemberTypes
.NestedType
|
639 MemberTypes
.Property
;
641 public const BindingFlags AllBindingFlags
=
642 BindingFlags
.Public
|
643 BindingFlags
.Static
|
644 BindingFlags
.Instance
;
646 public static Expression
MemberLookup (EmitContext ec
, Type queried_type
,
647 string name
, Location loc
)
649 return MemberLookup (ec
, ec
.ContainerType
, null, queried_type
, name
,
650 AllMemberTypes
, AllBindingFlags
, loc
);
653 public static Expression
MemberLookup (EmitContext ec
, Type qualifier_type
,
654 Type queried_type
, string name
, Location loc
)
656 return MemberLookup (ec
, ec
.ContainerType
, qualifier_type
, queried_type
,
657 name
, AllMemberTypes
, AllBindingFlags
, loc
);
660 public static Expression
MethodLookup (EmitContext ec
, Type queried_type
,
661 string name
, Location loc
)
663 return MemberLookup (ec
, ec
.ContainerType
, null, queried_type
, name
,
664 MemberTypes
.Method
, AllBindingFlags
, loc
);
668 /// This is a wrapper for MemberLookup that is not used to "probe", but
669 /// to find a final definition. If the final definition is not found, we
670 /// look for private members and display a useful debugging message if we
673 public static Expression
MemberLookupFinal (EmitContext ec
, Type qualifier_type
,
674 Type queried_type
, string name
, Location loc
)
676 return MemberLookupFinal (ec
, qualifier_type
, queried_type
, name
,
677 AllMemberTypes
, AllBindingFlags
, loc
);
680 public static Expression
MemberLookupFinal (EmitContext ec
, Type qualifier_type
,
681 Type queried_type
, string name
,
682 MemberTypes mt
, BindingFlags bf
,
687 int errors
= Report
.Errors
;
689 e
= MemberLookup (ec
, ec
.ContainerType
, qualifier_type
, queried_type
, name
, mt
, bf
, loc
);
691 if (e
== null && errors
== Report
.Errors
)
692 // No errors were reported by MemberLookup, but there was an error.
693 MemberLookupFailed (ec
, qualifier_type
, queried_type
, name
, null, true, loc
);
698 public static void MemberLookupFailed (EmitContext ec
, Type qualifier_type
,
699 Type queried_type
, string name
,
700 string class_name
, bool complain_if_none_found
,
703 if (almostMatchedMembers
.Count
!= 0) {
704 for (int i
= 0; i
< almostMatchedMembers
.Count
; ++i
) {
705 MemberInfo m
= (MemberInfo
) almostMatchedMembers
[i
];
706 for (int j
= 0; j
< i
; ++j
) {
707 if (m
== almostMatchedMembers
[j
]) {
715 Type declaring_type
= m
.DeclaringType
;
717 Report
.SymbolRelatedToPreviousError (m
);
718 if (qualifier_type
== null) {
719 Report
.Error (38, loc
, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
720 TypeManager
.CSharpName (m
.DeclaringType
),
721 TypeManager
.CSharpName (ec
.ContainerType
));
723 } else if (qualifier_type
!= ec
.ContainerType
&&
724 TypeManager
.IsNestedFamilyAccessible (ec
.ContainerType
, declaring_type
)) {
725 // Although a derived class can access protected members of
726 // its base class it cannot do so through an instance of the
727 // base class (CS1540). If the qualifier_type is a base of the
728 // ec.ContainerType and the lookup succeeds with the latter one,
729 // then we are in this situation.
730 Error_CannotAccessProtected (loc
, m
, qualifier_type
, ec
.ContainerType
);
732 ErrorIsInaccesible (loc
, TypeManager
.GetFullNameSignature (m
));
735 almostMatchedMembers
.Clear ();
739 MemberInfo
[] lookup
= TypeManager
.MemberLookup (queried_type
, null, queried_type
,
740 AllMemberTypes
, AllBindingFlags
|
741 BindingFlags
.NonPublic
, name
, null);
743 if (lookup
== null) {
744 if (!complain_if_none_found
)
747 if (class_name
!= null)
748 Report
.Error (103, loc
, "The name `{0}' does not exist in the context of `{1}'",
751 Error_TypeDoesNotContainDefinition (loc
, queried_type
, name
);
755 MemberList ml
= TypeManager
.FindMembers (queried_type
, MemberTypes
.Constructor
,
756 BindingFlags
.Static
| BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.DeclaredOnly
, null, null);
757 if (name
== ".ctor" && ml
.Count
== 0)
759 Report
.Error (143, loc
, "The type `{0}' has no constructors defined", TypeManager
.CSharpName (queried_type
));
763 ErrorIsInaccesible (loc
, TypeManager
.GetFullNameSignature (lookup
[0]));
767 /// Returns an expression that can be used to invoke operator true
768 /// on the expression if it exists.
770 static public StaticCallExpr
GetOperatorTrue (EmitContext ec
, Expression e
, Location loc
)
772 return GetOperatorTrueOrFalse (ec
, e
, true, loc
);
776 /// Returns an expression that can be used to invoke operator false
777 /// on the expression if it exists.
779 static public StaticCallExpr
GetOperatorFalse (EmitContext ec
, Expression e
, Location loc
)
781 return GetOperatorTrueOrFalse (ec
, e
, false, loc
);
784 static StaticCallExpr
GetOperatorTrueOrFalse (EmitContext ec
, Expression e
, bool is_true
, Location loc
)
787 Expression operator_group
;
789 operator_group
= MethodLookup (ec
, e
.Type
, is_true
? "op_True" : "op_False", loc
);
790 if (operator_group
== null)
793 ArrayList arguments
= new ArrayList ();
794 arguments
.Add (new Argument (e
, Argument
.AType
.Expression
));
795 method
= Invocation
.OverloadResolve (
796 ec
, (MethodGroupExpr
) operator_group
, arguments
, false, loc
);
801 return new StaticCallExpr ((MethodInfo
) method
, arguments
, loc
);
805 /// Resolves the expression `e' into a boolean expression: either through
806 /// an implicit conversion, or through an `operator true' invocation
808 public static Expression
ResolveBoolean (EmitContext ec
, Expression e
, Location loc
)
814 if (e
.Type
== TypeManager
.bool_type
)
817 Expression converted
= Convert
.ImplicitConversion (ec
, e
, TypeManager
.bool_type
, Location
.Null
);
819 if (converted
!= null)
823 // If no implicit conversion to bool exists, try using `operator true'
825 converted
= Expression
.GetOperatorTrue (ec
, e
, loc
);
826 if (converted
== null){
827 e
.Error_ValueCannotBeConverted (loc
, TypeManager
.bool_type
, false);
833 public virtual string ExprClassName
837 case ExprClass
.Invalid
:
839 case ExprClass
.Value
:
841 case ExprClass
.Variable
:
843 case ExprClass
.Namespace
:
847 case ExprClass
.MethodGroup
:
848 return "method group";
849 case ExprClass
.PropertyAccess
:
850 return "property access";
851 case ExprClass
.EventAccess
:
852 return "event access";
853 case ExprClass
.IndexerAccess
:
854 return "indexer access";
855 case ExprClass
.Nothing
:
858 throw new Exception ("Should not happen");
863 /// Reports that we were expecting `expr' to be of class `expected'
865 public void Error_UnexpectedKind (EmitContext ec
, string expected
, Location loc
)
867 Error_UnexpectedKind (ec
, expected
, ExprClassName
, loc
);
870 public void Error_UnexpectedKind (EmitContext ec
, string expected
, string was
, Location loc
)
872 string name
= GetSignatureForError ();
874 name
= ec
.DeclSpace
.GetSignatureForError () + '.' + name
;
876 Report
.Error (118, loc
, "`{0}' is a `{1}' but a `{2}' was expected",
877 name
, was
, expected
);
880 public void Error_UnexpectedKind (ResolveFlags flags
, Location loc
)
882 string [] valid
= new string [4];
885 if ((flags
& ResolveFlags
.VariableOrValue
) != 0) {
886 valid
[count
++] = "variable";
887 valid
[count
++] = "value";
890 if ((flags
& ResolveFlags
.Type
) != 0)
891 valid
[count
++] = "type";
893 if ((flags
& ResolveFlags
.MethodGroup
) != 0)
894 valid
[count
++] = "method group";
897 valid
[count
++] = "unknown";
899 StringBuilder sb
= new StringBuilder (valid
[0]);
900 for (int i
= 1; i
< count
- 1; i
++) {
902 sb
.Append (valid
[i
]);
905 sb
.Append ("' or `");
906 sb
.Append (valid
[count
- 1]);
909 Report
.Error (119, loc
,
910 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName
, sb
.ToString ());
913 public static void UnsafeError (Location loc
)
915 Report
.Error (214, loc
, "Pointers and fixed size buffers may only be used in an unsafe context");
919 // Load the object from the pointer.
921 public static void LoadFromPtr (ILGenerator ig
, Type t
)
923 if (t
== TypeManager
.int32_type
)
924 ig
.Emit (OpCodes
.Ldind_I4
);
925 else if (t
== TypeManager
.uint32_type
)
926 ig
.Emit (OpCodes
.Ldind_U4
);
927 else if (t
== TypeManager
.short_type
)
928 ig
.Emit (OpCodes
.Ldind_I2
);
929 else if (t
== TypeManager
.ushort_type
)
930 ig
.Emit (OpCodes
.Ldind_U2
);
931 else if (t
== TypeManager
.char_type
)
932 ig
.Emit (OpCodes
.Ldind_U2
);
933 else if (t
== TypeManager
.byte_type
)
934 ig
.Emit (OpCodes
.Ldind_U1
);
935 else if (t
== TypeManager
.sbyte_type
)
936 ig
.Emit (OpCodes
.Ldind_I1
);
937 else if (t
== TypeManager
.uint64_type
)
938 ig
.Emit (OpCodes
.Ldind_I8
);
939 else if (t
== TypeManager
.int64_type
)
940 ig
.Emit (OpCodes
.Ldind_I8
);
941 else if (t
== TypeManager
.float_type
)
942 ig
.Emit (OpCodes
.Ldind_R4
);
943 else if (t
== TypeManager
.double_type
)
944 ig
.Emit (OpCodes
.Ldind_R8
);
945 else if (t
== TypeManager
.bool_type
)
946 ig
.Emit (OpCodes
.Ldind_I1
);
947 else if (t
== TypeManager
.intptr_type
)
948 ig
.Emit (OpCodes
.Ldind_I
);
949 else if (TypeManager
.IsEnumType (t
)) {
950 if (t
== TypeManager
.enum_type
)
951 ig
.Emit (OpCodes
.Ldind_Ref
);
953 LoadFromPtr (ig
, TypeManager
.EnumToUnderlying (t
));
954 } else if (t
.IsValueType
)
955 ig
.Emit (OpCodes
.Ldobj
, t
);
956 else if (t
.IsPointer
)
957 ig
.Emit (OpCodes
.Ldind_I
);
959 ig
.Emit (OpCodes
.Ldind_Ref
);
963 // The stack contains the pointer and the value of type `type'
965 public static void StoreFromPtr (ILGenerator ig
, Type type
)
967 if (TypeManager
.IsEnumType (type
))
968 type
= TypeManager
.EnumToUnderlying (type
);
969 if (type
== TypeManager
.int32_type
|| type
== TypeManager
.uint32_type
)
970 ig
.Emit (OpCodes
.Stind_I4
);
971 else if (type
== TypeManager
.int64_type
|| type
== TypeManager
.uint64_type
)
972 ig
.Emit (OpCodes
.Stind_I8
);
973 else if (type
== TypeManager
.char_type
|| type
== TypeManager
.short_type
||
974 type
== TypeManager
.ushort_type
)
975 ig
.Emit (OpCodes
.Stind_I2
);
976 else if (type
== TypeManager
.float_type
)
977 ig
.Emit (OpCodes
.Stind_R4
);
978 else if (type
== TypeManager
.double_type
)
979 ig
.Emit (OpCodes
.Stind_R8
);
980 else if (type
== TypeManager
.byte_type
|| type
== TypeManager
.sbyte_type
||
981 type
== TypeManager
.bool_type
)
982 ig
.Emit (OpCodes
.Stind_I1
);
983 else if (type
== TypeManager
.intptr_type
)
984 ig
.Emit (OpCodes
.Stind_I
);
985 else if (type
.IsValueType
)
986 ig
.Emit (OpCodes
.Stobj
, type
);
988 ig
.Emit (OpCodes
.Stind_Ref
);
992 // Returns the size of type `t' if known, otherwise, 0
994 public static int GetTypeSize (Type t
)
996 t
= TypeManager
.TypeToCoreType (t
);
997 if (t
== TypeManager
.int32_type
||
998 t
== TypeManager
.uint32_type
||
999 t
== TypeManager
.float_type
)
1001 else if (t
== TypeManager
.int64_type
||
1002 t
== TypeManager
.uint64_type
||
1003 t
== TypeManager
.double_type
)
1005 else if (t
== TypeManager
.byte_type
||
1006 t
== TypeManager
.sbyte_type
||
1007 t
== TypeManager
.bool_type
)
1009 else if (t
== TypeManager
.short_type
||
1010 t
== TypeManager
.char_type
||
1011 t
== TypeManager
.ushort_type
)
1013 else if (t
== TypeManager
.decimal_type
)
1019 public static void Error_NegativeArrayIndex (Location loc
)
1021 Report
.Error (248, loc
, "Cannot create an array with a negative size");
1024 protected void Error_CannotCallAbstractBase (string name
)
1026 Report
.Error (205, loc
, "Cannot call an abstract base member `{0}'", name
);
1030 // Converts `source' to an int, uint, long or ulong.
1032 public Expression
ExpressionToArrayArgument (EmitContext ec
, Expression source
, Location loc
)
1036 bool old_checked
= ec
.CheckState
;
1037 ec
.CheckState
= true;
1039 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.int32_type
, loc
);
1040 if (target
== null){
1041 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.uint32_type
, loc
);
1042 if (target
== null){
1043 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.int64_type
, loc
);
1044 if (target
== null){
1045 target
= Convert
.ImplicitConversion (ec
, source
, TypeManager
.uint64_type
, loc
);
1047 source
.Error_ValueCannotBeConverted (loc
, TypeManager
.int32_type
, false);
1051 ec
.CheckState
= old_checked
;
1054 // Only positive constants are allowed at compile time
1056 if (target
is Constant
){
1057 if (target
is IntConstant
){
1058 if (((IntConstant
) target
).Value
< 0){
1059 Error_NegativeArrayIndex (loc
);
1064 if (target
is LongConstant
){
1065 if (((LongConstant
) target
).Value
< 0){
1066 Error_NegativeArrayIndex (loc
);
1079 /// This is just a base class for expressions that can
1080 /// appear on statements (invocations, object creation,
1081 /// assignments, post/pre increment and decrement). The idea
1082 /// being that they would support an extra Emition interface that
1083 /// does not leave a result on the stack.
1085 public abstract class ExpressionStatement
: Expression
{
1087 public virtual ExpressionStatement
ResolveStatement (EmitContext ec
)
1089 Expression e
= Resolve (ec
);
1093 ExpressionStatement es
= e
as ExpressionStatement
;
1095 Error (201, "Only assignment, call, increment, decrement and new object " +
1096 "expressions can be used as a statement");
1102 /// Requests the expression to be emitted in a `statement'
1103 /// context. This means that no new value is left on the
1104 /// stack after invoking this method (constrasted with
1105 /// Emit that will always leave a value on the stack).
1107 public abstract void EmitStatement (EmitContext ec
);
1111 /// This kind of cast is used to encapsulate the child
1112 /// whose type is child.Type into an expression that is
1113 /// reported to return "return_type". This is used to encapsulate
1114 /// expressions which have compatible types, but need to be dealt
1115 /// at higher levels with.
1117 /// For example, a "byte" expression could be encapsulated in one
1118 /// of these as an "unsigned int". The type for the expression
1119 /// would be "unsigned int".
1122 public class EmptyCast
: Expression
{
1123 protected Expression child
;
1125 public Expression Child
{
1131 public EmptyCast (Expression child
, Type return_type
)
1133 eclass
= child
.eclass
;
1134 loc
= child
.Location
;
1139 public override Expression
DoResolve (EmitContext ec
)
1141 // This should never be invoked, we are born in fully
1142 // initialized state.
1147 public override void Emit (EmitContext ec
)
1153 /// This is a numeric cast to a Decimal
1155 public class CastToDecimal
: EmptyCast
{
1157 MethodInfo conversion_operator
;
1159 public CastToDecimal (Expression child
)
1160 : this (child
, false)
1164 public CastToDecimal (Expression child
, bool find_explicit
)
1165 : base (child
, TypeManager
.decimal_type
)
1167 conversion_operator
= GetConversionOperator (find_explicit
);
1169 if (conversion_operator
== null)
1170 throw new InternalErrorException ("Outer conversion routine is out of sync");
1173 // Returns the implicit operator that converts from
1174 // 'child.Type' to System.Decimal.
1175 MethodInfo
GetConversionOperator (bool find_explicit
)
1177 string operator_name
= find_explicit
? "op_Explicit" : "op_Implicit";
1179 MemberInfo
[] mi
= TypeManager
.MemberLookup (type
, type
, type
, MemberTypes
.Method
,
1180 BindingFlags
.Static
| BindingFlags
.Public
, operator_name
, null);
1182 foreach (MethodInfo oper
in mi
) {
1183 ParameterData pd
= TypeManager
.GetParameterData (oper
);
1185 if (pd
.ParameterType (0) == child
.Type
&& oper
.ReturnType
== type
)
1191 public override void Emit (EmitContext ec
)
1193 ILGenerator ig
= ec
.ig
;
1196 ig
.Emit (OpCodes
.Call
, conversion_operator
);
1201 /// This is an explicit numeric cast from a Decimal
1203 public class CastFromDecimal
: EmptyCast
1205 static IDictionary operators
;
1207 public CastFromDecimal (Expression child
, Type return_type
)
1208 : base (child
, return_type
)
1210 if (child
.Type
!= TypeManager
.decimal_type
)
1211 throw new InternalErrorException (
1212 "The expected type is Decimal, instead it is " + child
.Type
.FullName
);
1215 // Returns the explicit operator that converts from an
1216 // express of type System.Decimal to 'type'.
1217 public Expression
Resolve ()
1219 if (operators
== null) {
1220 MemberInfo
[] all_oper
= TypeManager
.MemberLookup (TypeManager
.decimal_type
,
1221 TypeManager
.decimal_type
, TypeManager
.decimal_type
, MemberTypes
.Method
,
1222 BindingFlags
.Static
| BindingFlags
.Public
, "op_Explicit", null);
1224 operators
= new System
.Collections
.Specialized
.HybridDictionary ();
1225 foreach (MethodInfo oper
in all_oper
) {
1226 ParameterData pd
= TypeManager
.GetParameterData (oper
);
1227 if (pd
.ParameterType (0) == TypeManager
.decimal_type
)
1228 operators
.Add (oper
.ReturnType
, oper
);
1232 return operators
.Contains (type
) ? this : null;
1235 public override void Emit (EmitContext ec
)
1237 ILGenerator ig
= ec
.ig
;
1240 ig
.Emit (OpCodes
.Call
, (MethodInfo
)operators
[type
]);
1245 // We need to special case this since an empty cast of
1246 // a NullLiteral is still a Constant
1248 public class NullCast
: Constant
{
1249 public Constant child
;
1251 public NullCast (Constant child
, Type return_type
):
1252 base (Location
.Null
)
1254 eclass
= child
.eclass
;
1259 override public string AsString ()
1264 public override object GetValue ()
1269 public override Expression
DoResolve (EmitContext ec
)
1271 // This should never be invoked, we are born in fully
1272 // initialized state.
1277 public override void Emit (EmitContext ec
)
1282 public override Constant
Increment ()
1284 throw new NotSupportedException ();
1287 public override bool IsDefaultValue
{
1293 public override bool IsNegative
{
1299 public override Constant
Reduce (EmitContext ec
, Type target_type
)
1301 if (type
== target_type
)
1302 return child
.Reduce (ec
, target_type
);
1311 /// This class is used to wrap literals which belong inside Enums
1313 public class EnumConstant
: Constant
{
1314 public Constant Child
;
1316 public EnumConstant (Constant child
, Type enum_type
):
1317 base (child
.Location
)
1319 eclass
= child
.eclass
;
1324 public override Expression
DoResolve (EmitContext ec
)
1326 // This should never be invoked, we are born in fully
1327 // initialized state.
1332 public override void Emit (EmitContext ec
)
1337 public override string GetSignatureForError()
1339 return TypeManager
.CSharpName (Type
);
1342 public override object GetValue ()
1344 return Child
.GetValue ();
1347 public override object GetTypedValue ()
1349 // FIXME: runtime is not ready to work with just emited enums
1350 if (!RootContext
.StdLib
) {
1351 return Child
.GetValue ();
1354 return System
.Enum
.ToObject (type
, Child
.GetValue ());
1357 public override string AsString ()
1359 return Child
.AsString ();
1362 public override DoubleConstant
ConvertToDouble ()
1364 return Child
.ConvertToDouble ();
1367 public override FloatConstant
ConvertToFloat ()
1369 return Child
.ConvertToFloat ();
1372 public override ULongConstant
ConvertToULong ()
1374 return Child
.ConvertToULong ();
1377 public override LongConstant
ConvertToLong ()
1379 return Child
.ConvertToLong ();
1382 public override UIntConstant
ConvertToUInt ()
1384 return Child
.ConvertToUInt ();
1387 public override IntConstant
ConvertToInt ()
1389 return Child
.ConvertToInt ();
1392 public override Constant
Increment()
1394 return new EnumConstant (Child
.Increment (), type
);
1397 public override bool IsDefaultValue
{
1399 return Child
.IsDefaultValue
;
1403 public override bool IsZeroInteger
{
1404 get { return Child.IsZeroInteger; }
1407 public override bool IsNegative
{
1409 return Child
.IsNegative
;
1413 public override Constant
Reduce(EmitContext ec
, Type target_type
)
1415 if (Child
.Type
== target_type
)
1418 return Child
.Reduce (ec
, target_type
);
1421 public override Constant
ToType (Type type
, Location loc
)
1424 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1425 if (TypeManager
.IsEnumType (type
.UnderlyingSystemType
))
1428 if (type
.UnderlyingSystemType
!= Child
.Type
)
1429 Child
= Child
.ToType (type
.UnderlyingSystemType
, loc
);
1433 if (!Convert
.ImplicitStandardConversionExists (Convert
.ConstantEC
, this, type
)){
1434 Error_ValueCannotBeConverted (loc
, type
, false);
1438 return Child
.ToType (type
, loc
);
1444 /// This kind of cast is used to encapsulate Value Types in objects.
1446 /// The effect of it is to box the value type emitted by the previous
1449 public class BoxedCast
: EmptyCast
{
1451 public BoxedCast (Expression expr
, Type target_type
)
1452 : base (expr
, target_type
)
1454 eclass
= ExprClass
.Value
;
1457 public override Expression
DoResolve (EmitContext ec
)
1459 // This should never be invoked, we are born in fully
1460 // initialized state.
1465 public override void Emit (EmitContext ec
)
1469 ec
.ig
.Emit (OpCodes
.Box
, child
.Type
);
1473 public class UnboxCast
: EmptyCast
{
1474 public UnboxCast (Expression expr
, Type return_type
)
1475 : base (expr
, return_type
)
1479 public override Expression
DoResolve (EmitContext ec
)
1481 // This should never be invoked, we are born in fully
1482 // initialized state.
1487 public override void Emit (EmitContext ec
)
1490 ILGenerator ig
= ec
.ig
;
1493 ig
.Emit (OpCodes
.Unbox
, t
);
1495 LoadFromPtr (ig
, t
);
1500 /// This is used to perform explicit numeric conversions.
1502 /// Explicit numeric conversions might trigger exceptions in a checked
1503 /// context, so they should generate the conv.ovf opcodes instead of
1506 public class ConvCast
: EmptyCast
{
1507 public enum Mode
: byte {
1508 I1_U1
, I1_U2
, I1_U4
, I1_U8
, I1_CH
,
1510 I2_I1
, I2_U1
, I2_U2
, I2_U4
, I2_U8
, I2_CH
,
1511 U2_I1
, U2_U1
, U2_I2
, U2_CH
,
1512 I4_I1
, I4_U1
, I4_I2
, I4_U2
, I4_U4
, I4_U8
, I4_CH
,
1513 U4_I1
, U4_U1
, U4_I2
, U4_U2
, U4_I4
, U4_CH
,
1514 I8_I1
, I8_U1
, I8_I2
, I8_U2
, I8_I4
, I8_U4
, I8_U8
, I8_CH
,
1515 U8_I1
, U8_U1
, U8_I2
, U8_U2
, U8_I4
, U8_U4
, U8_I8
, U8_CH
,
1516 CH_I1
, CH_U1
, CH_I2
,
1517 R4_I1
, R4_U1
, R4_I2
, R4_U2
, R4_I4
, R4_U4
, R4_I8
, R4_U8
, R4_CH
,
1518 R8_I1
, R8_U1
, R8_I2
, R8_U2
, R8_I4
, R8_U4
, R8_I8
, R8_U8
, R8_CH
, R8_R4
1523 public ConvCast (Expression child
, Type return_type
, Mode m
)
1524 : base (child
, return_type
)
1529 public override Expression
DoResolve (EmitContext ec
)
1531 // This should never be invoked, we are born in fully
1532 // initialized state.
1537 public override string ToString ()
1539 return String
.Format ("ConvCast ({0}, {1})", mode
, child
);
1542 public override void Emit (EmitContext ec
)
1544 ILGenerator ig
= ec
.ig
;
1550 case Mode
.I1_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1551 case Mode
.I1_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1552 case Mode
.I1_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1553 case Mode
.I1_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1554 case Mode
.I1_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1556 case Mode
.U1_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1557 case Mode
.U1_CH
: /* nothing */ break;
1559 case Mode
.I2_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1560 case Mode
.I2_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1561 case Mode
.I2_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1562 case Mode
.I2_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1563 case Mode
.I2_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1564 case Mode
.I2_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1566 case Mode
.U2_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1567 case Mode
.U2_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1568 case Mode
.U2_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1569 case Mode
.U2_CH
: /* nothing */ break;
1571 case Mode
.I4_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1572 case Mode
.I4_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1573 case Mode
.I4_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1574 case Mode
.I4_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1575 case Mode
.I4_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1576 case Mode
.I4_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1577 case Mode
.I4_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1579 case Mode
.U4_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1580 case Mode
.U4_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1581 case Mode
.U4_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1582 case Mode
.U4_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1583 case Mode
.U4_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4_Un
); break;
1584 case Mode
.U4_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1586 case Mode
.I8_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1587 case Mode
.I8_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1588 case Mode
.I8_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1589 case Mode
.I8_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1590 case Mode
.I8_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4
); break;
1591 case Mode
.I8_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1592 case Mode
.I8_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1593 case Mode
.I8_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1595 case Mode
.U8_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1596 case Mode
.U8_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1597 case Mode
.U8_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1598 case Mode
.U8_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1599 case Mode
.U8_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4_Un
); break;
1600 case Mode
.U8_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4_Un
); break;
1601 case Mode
.U8_I8
: ig
.Emit (OpCodes
.Conv_Ovf_I8_Un
); break;
1602 case Mode
.U8_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2_Un
); break;
1604 case Mode
.CH_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1_Un
); break;
1605 case Mode
.CH_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1_Un
); break;
1606 case Mode
.CH_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2_Un
); break;
1608 case Mode
.R4_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1609 case Mode
.R4_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1610 case Mode
.R4_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1611 case Mode
.R4_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1612 case Mode
.R4_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4
); break;
1613 case Mode
.R4_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1614 case Mode
.R4_I8
: ig
.Emit (OpCodes
.Conv_Ovf_I8
); break;
1615 case Mode
.R4_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1616 case Mode
.R4_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1618 case Mode
.R8_I1
: ig
.Emit (OpCodes
.Conv_Ovf_I1
); break;
1619 case Mode
.R8_U1
: ig
.Emit (OpCodes
.Conv_Ovf_U1
); break;
1620 case Mode
.R8_I2
: ig
.Emit (OpCodes
.Conv_Ovf_I2
); break;
1621 case Mode
.R8_U2
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1622 case Mode
.R8_I4
: ig
.Emit (OpCodes
.Conv_Ovf_I4
); break;
1623 case Mode
.R8_U4
: ig
.Emit (OpCodes
.Conv_Ovf_U4
); break;
1624 case Mode
.R8_I8
: ig
.Emit (OpCodes
.Conv_Ovf_I8
); break;
1625 case Mode
.R8_U8
: ig
.Emit (OpCodes
.Conv_Ovf_U8
); break;
1626 case Mode
.R8_CH
: ig
.Emit (OpCodes
.Conv_Ovf_U2
); break;
1627 case Mode
.R8_R4
: ig
.Emit (OpCodes
.Conv_R4
); break;
1631 case Mode
.I1_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1632 case Mode
.I1_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1633 case Mode
.I1_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1634 case Mode
.I1_U8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1635 case Mode
.I1_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1637 case Mode
.U1_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1638 case Mode
.U1_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1640 case Mode
.I2_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1641 case Mode
.I2_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1642 case Mode
.I2_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1643 case Mode
.I2_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1644 case Mode
.I2_U8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1645 case Mode
.I2_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1647 case Mode
.U2_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1648 case Mode
.U2_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1649 case Mode
.U2_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1650 case Mode
.U2_CH
: /* nothing */ break;
1652 case Mode
.I4_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1653 case Mode
.I4_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1654 case Mode
.I4_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1655 case Mode
.I4_U4
: /* nothing */ break;
1656 case Mode
.I4_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1657 case Mode
.I4_U8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1658 case Mode
.I4_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1660 case Mode
.U4_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1661 case Mode
.U4_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1662 case Mode
.U4_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1663 case Mode
.U4_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1664 case Mode
.U4_I4
: /* nothing */ break;
1665 case Mode
.U4_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1667 case Mode
.I8_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1668 case Mode
.I8_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1669 case Mode
.I8_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1670 case Mode
.I8_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1671 case Mode
.I8_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1672 case Mode
.I8_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1673 case Mode
.I8_U8
: /* nothing */ break;
1674 case Mode
.I8_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1676 case Mode
.U8_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1677 case Mode
.U8_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1678 case Mode
.U8_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1679 case Mode
.U8_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1680 case Mode
.U8_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1681 case Mode
.U8_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1682 case Mode
.U8_I8
: /* nothing */ break;
1683 case Mode
.U8_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1685 case Mode
.CH_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1686 case Mode
.CH_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1687 case Mode
.CH_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1689 case Mode
.R4_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1690 case Mode
.R4_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1691 case Mode
.R4_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1692 case Mode
.R4_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1693 case Mode
.R4_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1694 case Mode
.R4_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1695 case Mode
.R4_I8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1696 case Mode
.R4_U8
: ig
.Emit (OpCodes
.Conv_U8
); break;
1697 case Mode
.R4_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1699 case Mode
.R8_I1
: ig
.Emit (OpCodes
.Conv_I1
); break;
1700 case Mode
.R8_U1
: ig
.Emit (OpCodes
.Conv_U1
); break;
1701 case Mode
.R8_I2
: ig
.Emit (OpCodes
.Conv_I2
); break;
1702 case Mode
.R8_U2
: ig
.Emit (OpCodes
.Conv_U2
); break;
1703 case Mode
.R8_I4
: ig
.Emit (OpCodes
.Conv_I4
); break;
1704 case Mode
.R8_U4
: ig
.Emit (OpCodes
.Conv_U4
); break;
1705 case Mode
.R8_I8
: ig
.Emit (OpCodes
.Conv_I8
); break;
1706 case Mode
.R8_U8
: ig
.Emit (OpCodes
.Conv_U8
); break;
1707 case Mode
.R8_CH
: ig
.Emit (OpCodes
.Conv_U2
); break;
1708 case Mode
.R8_R4
: ig
.Emit (OpCodes
.Conv_R4
); break;
1714 public class OpcodeCast
: EmptyCast
{
1718 public OpcodeCast (Expression child
, Type return_type
, OpCode op
)
1719 : base (child
, return_type
)
1723 second_valid
= false;
1726 public OpcodeCast (Expression child
, Type return_type
, OpCode op
, OpCode op2
)
1727 : base (child
, return_type
)
1732 second_valid
= true;
1735 public override Expression
DoResolve (EmitContext ec
)
1737 // This should never be invoked, we are born in fully
1738 // initialized state.
1743 public override void Emit (EmitContext ec
)
1754 /// This kind of cast is used to encapsulate a child and cast it
1755 /// to the class requested
1757 public class ClassCast
: EmptyCast
{
1758 public ClassCast (Expression child
, Type return_type
)
1759 : base (child
, return_type
)
1764 public override Expression
DoResolve (EmitContext ec
)
1766 // This should never be invoked, we are born in fully
1767 // initialized state.
1772 public override void Emit (EmitContext ec
)
1776 ec
.ig
.Emit (OpCodes
.Castclass
, type
);
1782 /// SimpleName expressions are formed of a single word and only happen at the beginning
1783 /// of a dotted-name.
1785 public class SimpleName
: Expression
{
1789 public SimpleName (string name
, Location l
)
1795 public static void Error_ObjectRefRequired (EmitContext ec
, Location l
, string name
)
1797 if (ec
.IsFieldInitializer
)
1798 Report
.Error (236, l
,
1799 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1802 if (name
.LastIndexOf ('.') > 0)
1803 name
= name
.Substring (name
.LastIndexOf ('.') + 1);
1806 120, l
, "`{0}': An object reference is required for the nonstatic field, method or property",
1811 public bool IdenticalNameAndTypeName (EmitContext ec
, Expression resolved_to
, Location loc
)
1813 return resolved_to
!= null && resolved_to
.Type
!= null &&
1814 resolved_to
.Type
.Name
== Name
&&
1815 (ec
.DeclSpace
.LookupType (Name
, loc
, /* ignore_cs0104 = */ true) != null);
1818 public override Expression
DoResolve (EmitContext ec
)
1820 return SimpleNameResolve (ec
, null, false);
1823 public override Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
1825 return SimpleNameResolve (ec
, right_side
, false);
1829 public Expression
DoResolve (EmitContext ec
, bool intermediate
)
1831 return SimpleNameResolve (ec
, null, intermediate
);
1834 public override FullNamedExpression
ResolveAsTypeStep (EmitContext ec
, bool silent
)
1836 int errors
= Report
.Errors
;
1837 FullNamedExpression fne
= ec
.DeclSpace
.LookupType (Name
, loc
, /*ignore_cs0104=*/ false);
1841 if (silent
|| errors
!= Report
.Errors
)
1844 MemberCore mc
= ec
.DeclSpace
.GetDefinition (Name
);
1846 Error_UnexpectedKind (ec
, "type", GetMemberType (mc
), loc
);
1848 NamespaceEntry
.Error_NamespaceNotFound (loc
, Name
);
1854 // TODO: I am still not convinced about this. If someone else will need it
1855 // implement this as virtual property in MemberCore hierarchy
1856 string GetMemberType (MemberCore mc
)
1858 if (mc
is PropertyBase
)
1862 if (mc
is FieldBase
)
1864 if (mc
is MethodCore
)
1866 if (mc
is EnumMember
)
1872 Expression
SimpleNameResolve (EmitContext ec
, Expression right_side
, bool intermediate
)
1878 Expression e
= DoSimpleNameResolve (ec
, right_side
, intermediate
);
1882 if (ec
.CurrentBlock
== null || ec
.CurrentBlock
.CheckInvariantMeaningInBlock (Name
, e
, Location
))
1889 /// 7.5.2: Simple Names.
1891 /// Local Variables and Parameters are handled at
1892 /// parse time, so they never occur as SimpleNames.
1894 /// The `intermediate' flag is used by MemberAccess only
1895 /// and it is used to inform us that it is ok for us to
1896 /// avoid the static check, because MemberAccess might end
1897 /// up resolving the Name as a Type name and the access as
1898 /// a static type access.
1900 /// ie: Type Type; .... { Type.GetType (""); }
1902 /// Type is both an instance variable and a Type; Type.GetType
1903 /// is the static method not an instance method of type.
1905 Expression
DoSimpleNameResolve (EmitContext ec
, Expression right_side
, bool intermediate
)
1907 Expression e
= null;
1910 // Stage 1: Performed by the parser (binding to locals or parameters).
1912 Block current_block
= ec
.CurrentBlock
;
1913 if (current_block
!= null){
1914 LocalInfo vi
= current_block
.GetLocalInfo (Name
);
1916 LocalVariableReference
var = new LocalVariableReference (ec
.CurrentBlock
, Name
, loc
);
1917 if (right_side
!= null) {
1918 return var.ResolveLValue (ec
, right_side
, loc
);
1920 ResolveFlags rf
= ResolveFlags
.VariableOrValue
;
1922 rf
|= ResolveFlags
.DisableFlowAnalysis
;
1923 return var.Resolve (ec
, rf
);
1927 ParameterReference pref
= current_block
.Toplevel
.GetParameterReference (Name
, loc
);
1929 if (right_side
!= null)
1930 return pref
.ResolveLValue (ec
, right_side
, loc
);
1932 return pref
.Resolve (ec
);
1937 // Stage 2: Lookup members
1940 DeclSpace lookup_ds
= ec
.DeclSpace
;
1941 Type almost_matched_type
= null;
1942 ArrayList almost_matched
= null;
1944 if (lookup_ds
.TypeBuilder
== null)
1947 e
= MemberLookup (ec
, lookup_ds
.TypeBuilder
, Name
, loc
);
1951 if (almost_matched
== null && almostMatchedMembers
.Count
> 0) {
1952 almost_matched_type
= lookup_ds
.TypeBuilder
;
1953 almost_matched
= (ArrayList
) almostMatchedMembers
.Clone ();
1956 lookup_ds
=lookup_ds
.Parent
;
1957 } while (lookup_ds
!= null);
1959 if (e
== null && ec
.ContainerType
!= null)
1960 e
= MemberLookup (ec
, ec
.ContainerType
, Name
, loc
);
1963 if (almost_matched
== null && almostMatchedMembers
.Count
> 0) {
1964 almost_matched_type
= ec
.ContainerType
;
1965 almost_matched
= (ArrayList
) almostMatchedMembers
.Clone ();
1967 e
= ResolveAsTypeStep (ec
, true);
1971 if (almost_matched
!= null)
1972 almostMatchedMembers
= almost_matched
;
1973 if (almost_matched_type
== null)
1974 almost_matched_type
= ec
.ContainerType
;
1975 MemberLookupFailed (ec
, null, almost_matched_type
, ((SimpleName
) this).Name
, ec
.DeclSpace
.Name
, true, loc
);
1982 if (e
is MemberExpr
) {
1983 MemberExpr me
= (MemberExpr
) e
;
1986 if (me
.IsInstance
) {
1987 if (ec
.IsStatic
|| ec
.IsFieldInitializer
) {
1989 // Note that an MemberExpr can be both IsInstance and IsStatic.
1990 // An unresolved MethodGroupExpr can contain both kinds of methods
1991 // and each predicate is true if the MethodGroupExpr contains
1992 // at least one of that kind of method.
1996 (!intermediate
|| !IdenticalNameAndTypeName (ec
, me
, loc
))) {
1997 Error_ObjectRefRequired (ec
, loc
, me
.GetSignatureForError ());
1998 return EmptyExpression
.Null
;
2002 // Pass the buck to MemberAccess and Invocation.
2004 left
= EmptyExpression
.Null
;
2006 left
= ec
.GetThis (loc
);
2009 left
= new TypeExpression (ec
.ContainerType
, loc
);
2012 e
= me
.ResolveMemberAccess (ec
, left
, loc
, null);
2016 me
= e
as MemberExpr
;
2021 TypeManager
.IsNestedFamilyAccessible (me
.InstanceExpression
.Type
, me
.DeclaringType
) &&
2022 me
.InstanceExpression
.Type
!= me
.DeclaringType
&&
2023 !me
.InstanceExpression
.Type
.IsSubclassOf (me
.DeclaringType
) &&
2024 (!intermediate
|| !IdenticalNameAndTypeName (ec
, e
, loc
))) {
2025 Report
.Error (38, loc
, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2026 TypeManager
.CSharpName (me
.DeclaringType
), TypeManager
.CSharpName (me
.InstanceExpression
.Type
));
2030 return (right_side
!= null)
2031 ? me
.DoResolveLValue (ec
, right_side
)
2032 : me
.DoResolve (ec
);
2038 public override void Emit (EmitContext ec
)
2041 // If this is ever reached, then we failed to
2042 // find the name as a namespace
2045 Error (103, "The name `" + Name
+
2046 "' does not exist in the class `" +
2047 ec
.DeclSpace
.Name
+ "'");
2050 public override string ToString ()
2055 public override string GetSignatureForError ()
2062 /// Represents a namespace or a type. The name of the class was inspired by
2063 /// section 10.8.1 (Fully Qualified Names).
2065 public abstract class FullNamedExpression
: Expression
{
2066 public override FullNamedExpression
ResolveAsTypeStep (EmitContext ec
, bool silent
)
2071 public abstract string FullName
{
2077 /// Expression that evaluates to a type
2079 public abstract class TypeExpr
: FullNamedExpression
{
2080 override public FullNamedExpression
ResolveAsTypeStep (EmitContext ec
, bool silent
)
2082 TypeExpr t
= DoResolveAsTypeStep (ec
);
2086 eclass
= ExprClass
.Type
;
2090 override public Expression
DoResolve (EmitContext ec
)
2092 return ResolveAsTypeTerminal (ec
, false);
2095 override public void Emit (EmitContext ec
)
2097 throw new Exception ("Should never be called");
2100 public virtual bool CheckAccessLevel (DeclSpace ds
)
2102 return ds
.CheckAccessLevel (Type
);
2105 public virtual bool AsAccessible (DeclSpace ds
, int flags
)
2107 return ds
.AsAccessible (Type
, flags
);
2110 public virtual bool IsClass
{
2111 get { return Type.IsClass; }
2114 public virtual bool IsValueType
{
2115 get { return Type.IsValueType; }
2118 public virtual bool IsInterface
{
2119 get { return Type.IsInterface; }
2122 public virtual bool IsSealed
{
2123 get { return Type.IsSealed; }
2126 public virtual bool CanInheritFrom ()
2128 if (Type
== TypeManager
.enum_type
||
2129 (Type
== TypeManager
.value_type
&& RootContext
.StdLib
) ||
2130 Type
== TypeManager
.multicast_delegate_type
||
2131 Type
== TypeManager
.delegate_type
||
2132 Type
== TypeManager
.array_type
)
2138 public abstract TypeExpr
DoResolveAsTypeStep (EmitContext ec
);
2140 public Type
ResolveType (EmitContext ec
)
2142 TypeExpr t
= ResolveAsTypeTerminal (ec
, false);
2146 if (ec
.TestObsoleteMethodUsage
) {
2147 ObsoleteAttribute obsolete_attr
= AttributeTester
.GetObsoleteAttribute (t
.Type
);
2148 if (obsolete_attr
!= null) {
2149 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, Name
, Location
);
2156 public abstract string Name
{
2160 public override bool Equals (object obj
)
2162 TypeExpr tobj
= obj
as TypeExpr
;
2166 return Type
== tobj
.Type
;
2169 public override int GetHashCode ()
2171 return Type
.GetHashCode ();
2174 public override string ToString ()
2181 /// Fully resolved Expression that already evaluated to a type
2183 public class TypeExpression
: TypeExpr
{
2184 public TypeExpression (Type t
, Location l
)
2187 eclass
= ExprClass
.Type
;
2191 public override TypeExpr
DoResolveAsTypeStep (EmitContext ec
)
2196 public override string Name
{
2197 get { return Type.ToString (); }
2200 public override string FullName
{
2201 get { return Type.FullName; }
2206 /// Used to create types from a fully qualified name. These are just used
2207 /// by the parser to setup the core types. A TypeLookupExpression is always
2208 /// classified as a type.
2210 public class TypeLookupExpression
: TypeExpr
{
2213 public TypeLookupExpression (string name
)
2218 static readonly char [] dot_array
= { '.' }
;
2219 public override TypeExpr
DoResolveAsTypeStep (EmitContext ec
)
2224 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2226 string lookup_name
= name
;
2227 int pos
= name
.IndexOf ('.');
2229 rest
= name
.Substring (pos
+ 1);
2230 lookup_name
= name
.Substring (0, pos
);
2233 FullNamedExpression resolved
= RootNamespace
.Global
.Lookup (ec
.DeclSpace
, lookup_name
, Location
.Null
);
2235 if (resolved
!= null && rest
!= null) {
2236 // Now handle the rest of the the name.
2237 string [] elements
= rest
.Split (dot_array
);
2239 int count
= elements
.Length
;
2241 while (i
< count
&& resolved
!= null && resolved
is Namespace
) {
2242 Namespace ns
= resolved
as Namespace
;
2243 element
= elements
[i
++];
2244 lookup_name
+= "." + element
;
2245 resolved
= ns
.Lookup (ec
.DeclSpace
, element
, Location
.Null
);
2248 if (resolved
!= null && resolved
is TypeExpr
) {
2249 Type t
= ((TypeExpr
) resolved
).Type
;
2251 if (!ec
.DeclSpace
.CheckAccessLevel (t
)) {
2253 lookup_name
= t
.FullName
;
2260 t
= TypeManager
.GetNestedType (t
, elements
[i
++]);
2265 if (resolved
== null) {
2266 NamespaceEntry
.Error_NamespaceNotFound (loc
, lookup_name
);
2270 if (!(resolved
is TypeExpr
)) {
2271 resolved
.Error_UnexpectedKind (ec
, "type", loc
);
2275 type
= ((TypeExpr
) resolved
).ResolveType (ec
);
2279 public override string Name
{
2280 get { return name; }
2283 public override string FullName
{
2284 get { return name; }
2288 public class TypeAliasExpression
: TypeExpr
{
2291 public TypeAliasExpression (TypeExpr texpr
, Location l
)
2294 loc
= texpr
.Location
;
2296 eclass
= ExprClass
.Type
;
2299 public override string Name
{
2300 get { return texpr.Name; }
2303 public override string FullName
{
2304 get { return texpr.FullName; }
2307 public override TypeExpr
DoResolveAsTypeStep (EmitContext ec
)
2309 Type type
= texpr
.ResolveType (ec
);
2313 return new TypeExpression (type
, loc
);
2316 public override bool CheckAccessLevel (DeclSpace ds
)
2318 return texpr
.CheckAccessLevel (ds
);
2321 public override bool AsAccessible (DeclSpace ds
, int flags
)
2323 return texpr
.AsAccessible (ds
, flags
);
2326 public override bool IsClass
{
2327 get { return texpr.IsClass; }
2330 public override bool IsValueType
{
2331 get { return texpr.IsValueType; }
2334 public override bool IsInterface
{
2335 get { return texpr.IsInterface; }
2338 public override bool IsSealed
{
2339 get { return texpr.IsSealed; }
2344 /// This class denotes an expression which evaluates to a member
2345 /// of a struct or a class.
2347 public abstract class MemberExpr
: Expression
2350 /// The name of this member.
2352 public abstract string Name
{
2357 /// Whether this is an instance member.
2359 public abstract bool IsInstance
{
2364 /// Whether this is a static member.
2366 public abstract bool IsStatic
{
2371 /// The type which declares this member.
2373 public abstract Type DeclaringType
{
2378 /// The instance expression associated with this member, if it's a
2379 /// non-static member.
2381 public Expression InstanceExpression
;
2383 public static void error176 (Location loc
, string name
)
2385 Report
.Error (176, loc
, "Static member `{0}' cannot be accessed " +
2386 "with an instance reference, qualify it with a type name instead", name
);
2389 protected bool CheckIntermediateModification ()
2391 if (!InstanceExpression
.Type
.IsValueType
)
2394 if (InstanceExpression
is UnboxCast
) {
2395 Report
.Error (445, loc
, "Cannot modify the result of an unboxing conversion");
2399 if (!(InstanceExpression
is IMemoryLocation
)) {
2400 Report
.Error (1612, loc
, "Cannot modify the return value of `{0}' because it is not a variable",
2401 InstanceExpression
.GetSignatureForError ());
2408 // TODO: possible optimalization
2409 // Cache resolved constant result in FieldBuilder <-> expression map
2410 public virtual Expression
ResolveMemberAccess (EmitContext ec
, Expression left
, Location loc
,
2411 SimpleName original
)
2415 // original == null || original.Resolve (...) ==> left
2418 if (left
is TypeExpr
) {
2420 SimpleName
.Error_ObjectRefRequired (ec
, loc
, Name
);
2428 if (original
!= null && original
.IdenticalNameAndTypeName (ec
, left
, loc
))
2431 error176 (loc
, GetSignatureForError ());
2435 InstanceExpression
= left
;
2440 protected void EmitInstance (EmitContext ec
, bool prepare_for_load
)
2445 if (InstanceExpression
== EmptyExpression
.Null
) {
2446 SimpleName
.Error_ObjectRefRequired (ec
, loc
, Name
);
2450 if (InstanceExpression
.Type
.IsValueType
) {
2451 if (InstanceExpression
is IMemoryLocation
) {
2452 ((IMemoryLocation
) InstanceExpression
).AddressOf (ec
, AddressOp
.LoadStore
);
2454 LocalTemporary t
= new LocalTemporary (ec
, InstanceExpression
.Type
);
2455 InstanceExpression
.Emit (ec
);
2457 t
.AddressOf (ec
, AddressOp
.Store
);
2460 InstanceExpression
.Emit (ec
);
2462 if (prepare_for_load
)
2463 ec
.ig
.Emit (OpCodes
.Dup
);
2468 /// MethodGroup Expression.
2470 /// This is a fully resolved expression that evaluates to a type
2472 public class MethodGroupExpr
: MemberExpr
{
2473 public MethodBase
[] Methods
;
2474 bool identical_type_name
= false;
2477 public MethodGroupExpr (MemberInfo
[] mi
, Location l
)
2479 Methods
= new MethodBase
[mi
.Length
];
2480 mi
.CopyTo (Methods
, 0);
2481 eclass
= ExprClass
.MethodGroup
;
2482 type
= TypeManager
.object_type
;
2486 public MethodGroupExpr (ArrayList list
, Location l
)
2488 Methods
= new MethodBase
[list
.Count
];
2491 list
.CopyTo (Methods
, 0);
2493 foreach (MemberInfo m
in list
){
2494 if (!(m
is MethodBase
)){
2495 Console
.WriteLine ("Name " + m
.Name
);
2496 Console
.WriteLine ("Found a: " + m
.GetType ().FullName
);
2503 eclass
= ExprClass
.MethodGroup
;
2504 type
= TypeManager
.object_type
;
2507 public override Type DeclaringType
{
2510 // The methods are arranged in this order:
2511 // derived type -> base type
2513 return Methods
[0].DeclaringType
;
2517 public bool IdenticalTypeName
{
2519 return identical_type_name
;
2523 identical_type_name
= value;
2527 public bool IsBase
{
2536 public override string GetSignatureForError ()
2538 return TypeManager
.CSharpSignature (Methods
[0]);
2541 public override string Name
{
2543 return Methods
[0].Name
;
2547 public override bool IsInstance
{
2549 foreach (MethodBase mb
in Methods
)
2557 public override bool IsStatic
{
2559 foreach (MethodBase mb
in Methods
)
2567 public override Expression
ResolveMemberAccess (EmitContext ec
, Expression left
, Location loc
,
2568 SimpleName original
)
2570 if (!(left
is TypeExpr
) &&
2571 original
!= null && original
.IdenticalNameAndTypeName (ec
, left
, loc
))
2572 IdenticalTypeName
= true;
2574 return base.ResolveMemberAccess (ec
, left
, loc
, original
);
2577 override public Expression
DoResolve (EmitContext ec
)
2580 InstanceExpression
= null;
2582 if (InstanceExpression
!= null) {
2583 InstanceExpression
= InstanceExpression
.DoResolve (ec
);
2584 if (InstanceExpression
== null)
2591 public void ReportUsageError ()
2593 Report
.Error (654, loc
, "Method `" + DeclaringType
+ "." +
2594 Name
+ "()' is referenced without parentheses");
2597 override public void Emit (EmitContext ec
)
2599 ReportUsageError ();
2602 bool RemoveMethods (bool keep_static
)
2604 ArrayList smethods
= new ArrayList ();
2606 foreach (MethodBase mb
in Methods
){
2607 if (mb
.IsStatic
== keep_static
)
2611 if (smethods
.Count
== 0)
2614 Methods
= new MethodBase
[smethods
.Count
];
2615 smethods
.CopyTo (Methods
, 0);
2621 /// Removes any instance methods from the MethodGroup, returns
2622 /// false if the resulting set is empty.
2624 public bool RemoveInstanceMethods ()
2626 return RemoveMethods (true);
2630 /// Removes any static methods from the MethodGroup, returns
2631 /// false if the resulting set is empty.
2633 public bool RemoveStaticMethods ()
2635 return RemoveMethods (false);
2640 /// Fully resolved expression that evaluates to a Field
2642 public class FieldExpr
: MemberExpr
, IAssignMethod
, IMemoryLocation
, IVariable
{
2643 public readonly FieldInfo FieldInfo
;
2644 VariableInfo variable_info
;
2646 LocalTemporary temp
;
2648 bool in_initializer
;
2650 public FieldExpr (FieldInfo fi
, Location l
, bool in_initializer
):
2653 this.in_initializer
= in_initializer
;
2656 public FieldExpr (FieldInfo fi
, Location l
)
2659 eclass
= ExprClass
.Variable
;
2660 type
= fi
.FieldType
;
2664 public override string Name
{
2666 return FieldInfo
.Name
;
2670 public override bool IsInstance
{
2672 return !FieldInfo
.IsStatic
;
2676 public override bool IsStatic
{
2678 return FieldInfo
.IsStatic
;
2682 public override Type DeclaringType
{
2684 return FieldInfo
.DeclaringType
;
2688 public override string GetSignatureForError ()
2690 return TypeManager
.GetFullNameSignature (FieldInfo
);
2693 public VariableInfo VariableInfo
{
2695 return variable_info
;
2699 public override Expression
ResolveMemberAccess (EmitContext ec
, Expression left
, Location loc
,
2700 SimpleName original
)
2702 Type t
= FieldInfo
.FieldType
;
2704 if (FieldInfo
.IsLiteral
|| (FieldInfo
.IsInitOnly
&& t
== TypeManager
.decimal_type
)) {
2705 IConstant ic
= TypeManager
.GetConstant (FieldInfo
);
2707 if (FieldInfo
.IsLiteral
) {
2708 ic
= new ExternalConstant (FieldInfo
);
2710 ic
= ExternalConstant
.CreateDecimal (FieldInfo
);
2712 return base.ResolveMemberAccess (ec
, left
, loc
, original
);
2715 TypeManager
.RegisterConstant (FieldInfo
, ic
);
2718 bool left_is_type
= left
is TypeExpr
;
2719 if (!left_is_type
&& (original
== null || !original
.IdenticalNameAndTypeName (ec
, left
, loc
))) {
2720 Report
.SymbolRelatedToPreviousError (FieldInfo
);
2721 error176 (loc
, TypeManager
.GetFullNameSignature (FieldInfo
));
2725 if (ic
.ResolveValue ()) {
2726 if (ec
.TestObsoleteMethodUsage
)
2727 ic
.CheckObsoleteness (loc
);
2733 if (t
.IsPointer
&& !ec
.InUnsafe
) {
2738 return base.ResolveMemberAccess (ec
, left
, loc
, original
);
2741 override public Expression
DoResolve (EmitContext ec
)
2743 if (ec
.InRefOutArgumentResolving
&& FieldInfo
.IsInitOnly
&& !ec
.IsConstructor
&& FieldInfo
.FieldType
.IsValueType
) {
2744 if (FieldInfo
.FieldType
is TypeBuilder
) {
2745 if (FieldInfo
.IsStatic
)
2746 Report
.Error (1651, loc
, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2747 GetSignatureForError ());
2749 Report
.Error (1649, loc
, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
2750 TypeManager
.CSharpName (DeclaringType
), Name
);
2752 if (FieldInfo
.IsStatic
)
2753 Report
.Error (199, loc
, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2756 Report
.Error (192, loc
, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2762 if (!FieldInfo
.IsStatic
){
2763 if (InstanceExpression
== null){
2765 // This can happen when referencing an instance field using
2766 // a fully qualified type expression: TypeName.InstanceField = xxx
2768 SimpleName
.Error_ObjectRefRequired (ec
, loc
, FieldInfo
.Name
);
2772 // Resolve the field's instance expression while flow analysis is turned
2773 // off: when accessing a field "a.b", we must check whether the field
2774 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2775 InstanceExpression
= InstanceExpression
.Resolve (
2776 ec
, ResolveFlags
.VariableOrValue
| ResolveFlags
.DisableFlowAnalysis
);
2777 if (InstanceExpression
== null)
2781 if (!in_initializer
&& !ec
.IsFieldInitializer
) {
2782 ObsoleteAttribute oa
;
2783 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2785 if (ec
.TestObsoleteMethodUsage
)
2786 f
.CheckObsoleteness (loc
);
2788 // To be sure that type is external because we do not register generated fields
2789 } else if (!(FieldInfo
.DeclaringType
is TypeBuilder
)) {
2790 oa
= AttributeTester
.GetMemberObsoleteAttribute (FieldInfo
);
2792 AttributeTester
.Report_ObsoleteMessage (oa
, TypeManager
.GetFullNameSignature (FieldInfo
), loc
);
2796 AnonymousContainer am
= ec
.CurrentAnonymousMethod
;
2798 if (!FieldInfo
.IsStatic
){
2799 if (!am
.IsIterator
&& (ec
.TypeContainer
is Struct
)){
2800 Report
.Error (1673, loc
,
2801 "Anonymous methods inside structs cannot access instance members of `{0}'. Consider copying `{0}' to a local variable outside the anonymous method and using the local instead",
2805 if ((am
.ContainerAnonymousMethod
== null) && (InstanceExpression
is This
))
2806 ec
.CaptureField (this);
2810 // If the instance expression is a local variable or parameter.
2811 IVariable
var = InstanceExpression
as IVariable
;
2812 if ((var == null) || (var.VariableInfo
== null))
2815 VariableInfo vi
= var.VariableInfo
;
2816 if (!vi
.IsFieldAssigned (ec
, FieldInfo
.Name
, loc
))
2819 variable_info
= vi
.GetSubStruct (FieldInfo
.Name
);
2823 void Report_AssignToReadonly (bool is_instance
)
2828 msg
= "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
2830 msg
= "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
2832 Report
.Error (is_instance
? 191 : 198, loc
, msg
);
2835 override public Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
2837 IVariable
var = InstanceExpression
as IVariable
;
2838 if ((var != null) && (var.VariableInfo
!= null))
2839 var.VariableInfo
.SetFieldAssigned (ec
, FieldInfo
.Name
);
2841 Expression e
= DoResolve (ec
);
2846 if (!FieldInfo
.IsStatic
&& !CheckIntermediateModification ())
2849 FieldBase fb
= TypeManager
.GetField (FieldInfo
);
2853 if (!FieldInfo
.IsInitOnly
)
2857 // InitOnly fields can only be assigned in constructors
2860 if (ec
.IsConstructor
){
2861 if (IsStatic
&& !ec
.IsStatic
)
2862 Report_AssignToReadonly (false);
2864 if (ec
.ContainerType
== FieldInfo
.DeclaringType
)
2868 Report_AssignToReadonly (!IsStatic
);
2873 public override void CheckMarshallByRefAccess (Type container
)
2875 if (!IsStatic
&& Type
.IsValueType
&& !container
.IsSubclassOf (TypeManager
.mbr_type
) && DeclaringType
.IsSubclassOf (TypeManager
.mbr_type
)) {
2876 Report
.SymbolRelatedToPreviousError (DeclaringType
);
2877 Report
.Error (1690, loc
, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
2878 GetSignatureForError ());
2882 public bool VerifyFixed ()
2884 IVariable variable
= InstanceExpression
as IVariable
;
2885 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
2886 // We defer the InstanceExpression check after the variable check to avoid a
2887 // separate null check on InstanceExpression.
2888 return variable
!= null && InstanceExpression
.Type
.IsValueType
&& variable
.VerifyFixed ();
2891 public override int GetHashCode()
2893 return FieldInfo
.GetHashCode ();
2896 public override bool Equals (object obj
)
2898 FieldExpr fe
= obj
as FieldExpr
;
2902 if (FieldInfo
!= fe
.FieldInfo
)
2905 if (InstanceExpression
== null || fe
.InstanceExpression
== null)
2908 return InstanceExpression
.Equals (fe
.InstanceExpression
);
2911 public void Emit (EmitContext ec
, bool leave_copy
)
2913 ILGenerator ig
= ec
.ig
;
2914 bool is_volatile
= false;
2916 if (FieldInfo
is FieldBuilder
){
2917 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2919 if ((f
.ModFlags
& Modifiers
.VOLATILE
) != 0)
2922 f
.SetMemberIsUsed ();
2926 if (FieldInfo
.IsStatic
){
2928 ig
.Emit (OpCodes
.Volatile
);
2930 ig
.Emit (OpCodes
.Ldsfld
, FieldInfo
);
2933 EmitInstance (ec
, false);
2936 ig
.Emit (OpCodes
.Volatile
);
2938 IFixedBuffer ff
= AttributeTester
.GetFixedBuffer (FieldInfo
);
2941 ig
.Emit (OpCodes
.Ldflda
, FieldInfo
);
2942 ig
.Emit (OpCodes
.Ldflda
, ff
.Element
);
2945 ig
.Emit (OpCodes
.Ldfld
, FieldInfo
);
2950 ec
.ig
.Emit (OpCodes
.Dup
);
2951 if (!FieldInfo
.IsStatic
) {
2952 temp
= new LocalTemporary (ec
, this.Type
);
2958 public void EmitAssign (EmitContext ec
, Expression source
, bool leave_copy
, bool prepare_for_load
)
2960 FieldAttributes fa
= FieldInfo
.Attributes
;
2961 bool is_static
= (fa
& FieldAttributes
.Static
) != 0;
2962 bool is_readonly
= (fa
& FieldAttributes
.InitOnly
) != 0;
2963 ILGenerator ig
= ec
.ig
;
2964 prepared
= prepare_for_load
;
2966 if (is_readonly
&& !ec
.IsConstructor
){
2967 Report_AssignToReadonly (!is_static
);
2971 EmitInstance (ec
, prepare_for_load
);
2975 ec
.ig
.Emit (OpCodes
.Dup
);
2976 if (!FieldInfo
.IsStatic
) {
2977 temp
= new LocalTemporary (ec
, this.Type
);
2982 if (FieldInfo
is FieldBuilder
){
2983 FieldBase f
= TypeManager
.GetField (FieldInfo
);
2985 if ((f
.ModFlags
& Modifiers
.VOLATILE
) != 0)
2986 ig
.Emit (OpCodes
.Volatile
);
2993 ig
.Emit (OpCodes
.Stsfld
, FieldInfo
);
2995 ig
.Emit (OpCodes
.Stfld
, FieldInfo
);
3001 public override void Emit (EmitContext ec
)
3006 public void AddressOf (EmitContext ec
, AddressOp mode
)
3008 ILGenerator ig
= ec
.ig
;
3010 if (FieldInfo
is FieldBuilder
){
3011 FieldBase f
= TypeManager
.GetField (FieldInfo
);
3013 if ((f
.ModFlags
& Modifiers
.VOLATILE
) != 0){
3014 Report
.Warning (420, 1, loc
, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3015 f
.GetSignatureForError ());
3019 if ((mode
& AddressOp
.Store
) != 0)
3021 if ((mode
& AddressOp
.Load
) != 0)
3022 f
.SetMemberIsUsed ();
3027 // Handle initonly fields specially: make a copy and then
3028 // get the address of the copy.
3031 if (FieldInfo
.IsInitOnly
){
3033 if (ec
.IsConstructor
){
3034 if (FieldInfo
.IsStatic
){
3046 local
= ig
.DeclareLocal (type
);
3047 ig
.Emit (OpCodes
.Stloc
, local
);
3048 ig
.Emit (OpCodes
.Ldloca
, local
);
3053 if (FieldInfo
.IsStatic
){
3054 ig
.Emit (OpCodes
.Ldsflda
, FieldInfo
);
3056 EmitInstance (ec
, false);
3057 ig
.Emit (OpCodes
.Ldflda
, FieldInfo
);
3063 // A FieldExpr whose address can not be taken
3065 public class FieldExprNoAddress
: FieldExpr
, IMemoryLocation
{
3066 public FieldExprNoAddress (FieldInfo fi
, Location loc
) : base (fi
, loc
)
3070 public new void AddressOf (EmitContext ec
, AddressOp mode
)
3072 Report
.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3077 /// Expression that evaluates to a Property. The Assign class
3078 /// might set the `Value' expression if we are in an assignment.
3080 /// This is not an LValue because we need to re-write the expression, we
3081 /// can not take data from the stack and store it.
3083 public class PropertyExpr
: MemberExpr
, IAssignMethod
{
3084 public readonly PropertyInfo PropertyInfo
;
3087 // This is set externally by the `BaseAccess' class
3090 MethodInfo getter
, setter
;
3095 LocalTemporary temp
;
3098 internal static PtrHashtable AccessorTable
= new PtrHashtable ();
3100 public PropertyExpr (EmitContext ec
, PropertyInfo pi
, Location l
)
3103 eclass
= ExprClass
.PropertyAccess
;
3107 type
= TypeManager
.TypeToCoreType (pi
.PropertyType
);
3109 ResolveAccessors (ec
);
3112 public override string Name
{
3114 return PropertyInfo
.Name
;
3118 public override bool IsInstance
{
3124 public override bool IsStatic
{
3130 public override Type DeclaringType
{
3132 return PropertyInfo
.DeclaringType
;
3136 public override string GetSignatureForError ()
3138 return TypeManager
.GetFullNameSignature (PropertyInfo
);
3141 void FindAccessors (Type invocation_type
)
3143 BindingFlags flags
= BindingFlags
.Public
| BindingFlags
.NonPublic
|
3144 BindingFlags
.Static
| BindingFlags
.Instance
|
3145 BindingFlags
.DeclaredOnly
;
3147 Type current
= PropertyInfo
.DeclaringType
;
3148 for (; current
!= null; current
= current
.BaseType
) {
3149 MemberInfo
[] group = TypeManager
.MemberLookup (
3150 invocation_type
, invocation_type
, current
,
3151 MemberTypes
.Property
, flags
, PropertyInfo
.Name
, null);
3156 if (group.Length
!= 1)
3157 // Oooops, can this ever happen ?
3160 PropertyInfo pi
= (PropertyInfo
) group [0];
3163 getter
= pi
.GetGetMethod (true);
3166 setter
= pi
.GetSetMethod (true);
3168 MethodInfo accessor
= getter
!= null ? getter
: setter
;
3170 if (!accessor
.IsVirtual
)
3176 // We also perform the permission checking here, as the PropertyInfo does not
3177 // hold the information for the accessibility of its setter/getter
3179 void ResolveAccessors (EmitContext ec
)
3181 FindAccessors (ec
.ContainerType
);
3183 if (getter
!= null) {
3184 IMethodData md
= TypeManager
.GetMethod (getter
);
3186 md
.SetMemberIsUsed ();
3188 AccessorTable
[getter
] = PropertyInfo
;
3189 is_static
= getter
.IsStatic
;
3192 if (setter
!= null) {
3193 IMethodData md
= TypeManager
.GetMethod (setter
);
3195 md
.SetMemberIsUsed ();
3197 AccessorTable
[setter
] = PropertyInfo
;
3198 is_static
= setter
.IsStatic
;
3202 bool InstanceResolve (EmitContext ec
, bool must_do_cs1540_check
)
3205 InstanceExpression
= null;
3209 if (InstanceExpression
== null) {
3210 SimpleName
.Error_ObjectRefRequired (ec
, loc
, PropertyInfo
.Name
);
3214 InstanceExpression
= InstanceExpression
.DoResolve (ec
);
3215 if (InstanceExpression
== null)
3218 InstanceExpression
.CheckMarshallByRefAccess (ec
.ContainerType
);
3220 if (must_do_cs1540_check
&& InstanceExpression
!= EmptyExpression
.Null
&&
3221 InstanceExpression
.Type
!= ec
.ContainerType
&&
3222 ec
.ContainerType
.IsSubclassOf (PropertyInfo
.DeclaringType
) &&
3223 InstanceExpression
.Type
.IsSubclassOf (PropertyInfo
.DeclaringType
)) {
3224 Error_CannotAccessProtected (loc
, PropertyInfo
, InstanceExpression
.Type
, ec
.ContainerType
);
3231 void Error_PropertyNotFound (MethodInfo mi
, bool getter
)
3233 // TODO: correctly we should compare arguments but it will lead to bigger changes
3234 if (mi
is MethodBuilder
) {
3235 Error_TypeDoesNotContainDefinition (loc
, PropertyInfo
.DeclaringType
, Name
);
3239 StringBuilder sig
= new StringBuilder (TypeManager
.CSharpName (mi
.DeclaringType
));
3241 ParameterData iparams
= TypeManager
.GetParameterData (mi
);
3242 sig
.Append (getter
? "get_" : "set_");
3244 sig
.Append (iparams
.GetSignatureForError ());
3246 Report
.SymbolRelatedToPreviousError (mi
);
3247 Report
.Error (1546, loc
, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3248 Name
, sig
.ToString ());
3251 override public Expression
DoResolve (EmitContext ec
)
3256 if (getter
!= null){
3257 if (TypeManager
.GetParameterData (getter
).Count
!= 0){
3258 Error_PropertyNotFound (getter
, true);
3263 if (getter
== null){
3265 // The following condition happens if the PropertyExpr was
3266 // created, but is invalid (ie, the property is inaccessible),
3267 // and we did not want to embed the knowledge about this in
3268 // the caller routine. This only avoids double error reporting.
3273 if (InstanceExpression
!= EmptyExpression
.Null
) {
3274 Report
.Error (154, loc
, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3275 TypeManager
.GetFullNameSignature (PropertyInfo
));
3280 bool must_do_cs1540_check
= false;
3281 if (getter
!= null &&
3282 !IsAccessorAccessible (ec
.ContainerType
, getter
, out must_do_cs1540_check
)) {
3283 PropertyBase
.PropertyMethod pm
= TypeManager
.GetMethod (getter
) as PropertyBase
.PropertyMethod
;
3284 if (pm
!= null && pm
.HasCustomAccessModifier
) {
3285 Report
.SymbolRelatedToPreviousError (pm
);
3286 Report
.Error (271, loc
, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3287 TypeManager
.CSharpSignature (getter
));
3290 ErrorIsInaccesible (loc
, TypeManager
.CSharpSignature (getter
));
3294 if (!InstanceResolve (ec
, must_do_cs1540_check
))
3298 // Only base will allow this invocation to happen.
3300 if (IsBase
&& getter
.IsAbstract
) {
3301 Error_CannotCallAbstractBase (TypeManager
.GetFullNameSignature (PropertyInfo
));
3305 if (PropertyInfo
.PropertyType
.IsPointer
&& !ec
.InUnsafe
){
3315 override public Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
3317 if (setter
== null){
3319 // The following condition happens if the PropertyExpr was
3320 // created, but is invalid (ie, the property is inaccessible),
3321 // and we did not want to embed the knowledge about this in
3322 // the caller routine. This only avoids double error reporting.
3327 Report
.Error (200, loc
, " Property or indexer `{0}' cannot be assigned to (it is read only)",
3328 TypeManager
.GetFullNameSignature (PropertyInfo
));
3332 if (TypeManager
.GetParameterData (setter
).Count
!= 1){
3333 Error_PropertyNotFound (setter
, false);
3337 bool must_do_cs1540_check
;
3338 if (!IsAccessorAccessible (ec
.ContainerType
, setter
, out must_do_cs1540_check
)) {
3339 PropertyBase
.PropertyMethod pm
= TypeManager
.GetMethod (setter
) as PropertyBase
.PropertyMethod
;
3340 if (pm
!= null && pm
.HasCustomAccessModifier
) {
3341 Report
.SymbolRelatedToPreviousError (pm
);
3342 Report
.Error (272, loc
, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3343 TypeManager
.CSharpSignature (setter
));
3346 ErrorIsInaccesible (loc
, TypeManager
.CSharpSignature (setter
));
3350 if (!InstanceResolve (ec
, must_do_cs1540_check
))
3354 // Only base will allow this invocation to happen.
3356 if (IsBase
&& setter
.IsAbstract
){
3357 Error_CannotCallAbstractBase (TypeManager
.GetFullNameSignature (PropertyInfo
));
3362 // Check that we are not making changes to a temporary memory location
3364 if (InstanceExpression
!= null && !CheckIntermediateModification ())
3370 public override void Emit (EmitContext ec
)
3375 public void Emit (EmitContext ec
, bool leave_copy
)
3378 // Special case: length of single dimension array property is turned into ldlen
3380 if ((getter
== TypeManager
.system_int_array_get_length
) ||
3381 (getter
== TypeManager
.int_array_get_length
)){
3382 Type iet
= InstanceExpression
.Type
;
3385 // System.Array.Length can be called, but the Type does not
3386 // support invoking GetArrayRank, so test for that case first
3388 if (iet
!= TypeManager
.array_type
&& (iet
.GetArrayRank () == 1)) {
3390 EmitInstance (ec
, false);
3391 ec
.ig
.Emit (OpCodes
.Ldlen
);
3392 ec
.ig
.Emit (OpCodes
.Conv_I4
);
3397 Invocation
.EmitCall (ec
, IsBase
, IsStatic
, InstanceExpression
, getter
, null, loc
, prepared
, false);
3400 ec
.ig
.Emit (OpCodes
.Dup
);
3402 temp
= new LocalTemporary (ec
, this.Type
);
3409 // Implements the IAssignMethod interface for assignments
3411 public void EmitAssign (EmitContext ec
, Expression source
, bool leave_copy
, bool prepare_for_load
)
3413 Expression my_source
= source
;
3415 prepared
= prepare_for_load
;
3420 ec
.ig
.Emit (OpCodes
.Dup
);
3422 temp
= new LocalTemporary (ec
, this.Type
);
3426 } else if (leave_copy
) {
3429 temp
= new LocalTemporary (ec
, this.Type
);
3435 ArrayList args
= new ArrayList (1);
3436 args
.Add (new Argument (my_source
, Argument
.AType
.Expression
));
3438 Invocation
.EmitCall (ec
, IsBase
, IsStatic
, InstanceExpression
, setter
, args
, loc
, false, prepared
);
3446 /// Fully resolved expression that evaluates to an Event
3448 public class EventExpr
: MemberExpr
{
3449 public readonly EventInfo EventInfo
;
3452 MethodInfo add_accessor
, remove_accessor
;
3454 public EventExpr (EventInfo ei
, Location loc
)
3458 eclass
= ExprClass
.EventAccess
;
3460 add_accessor
= TypeManager
.GetAddMethod (ei
);
3461 remove_accessor
= TypeManager
.GetRemoveMethod (ei
);
3463 if (add_accessor
.IsStatic
|| remove_accessor
.IsStatic
)
3466 if (EventInfo
is MyEventBuilder
){
3467 MyEventBuilder eb
= (MyEventBuilder
) EventInfo
;
3468 type
= eb
.EventType
;
3471 type
= EventInfo
.EventHandlerType
;
3474 public override string Name
{
3476 return EventInfo
.Name
;
3480 public override bool IsInstance
{
3486 public override bool IsStatic
{
3492 public override Type DeclaringType
{
3494 return EventInfo
.DeclaringType
;
3498 public override Expression
ResolveMemberAccess (EmitContext ec
, Expression left
, Location loc
,
3499 SimpleName original
)
3502 // If the event is local to this class, we transform ourselves into a FieldExpr
3505 if (EventInfo
.DeclaringType
== ec
.ContainerType
||
3506 TypeManager
.IsNestedChildOf(ec
.ContainerType
, EventInfo
.DeclaringType
)) {
3507 MemberInfo mi
= TypeManager
.GetPrivateFieldOfEvent (EventInfo
);
3510 MemberExpr ml
= (MemberExpr
) ExprClassFromMemberInfo (ec
, mi
, loc
);
3513 Report
.Error (-200, loc
, "Internal error!!");
3517 InstanceExpression
= null;
3519 return ml
.ResolveMemberAccess (ec
, left
, loc
, original
);
3523 return base.ResolveMemberAccess (ec
, left
, loc
, original
);
3527 bool InstanceResolve (EmitContext ec
, bool must_do_cs1540_check
)
3530 InstanceExpression
= null;
3534 if (InstanceExpression
== null) {
3535 SimpleName
.Error_ObjectRefRequired (ec
, loc
, EventInfo
.Name
);
3539 InstanceExpression
= InstanceExpression
.DoResolve (ec
);
3540 if (InstanceExpression
== null)
3544 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3545 // However, in the Event case, we reported a CS0122 instead.
3547 if (must_do_cs1540_check
&& InstanceExpression
!= EmptyExpression
.Null
) {
3548 if ((InstanceExpression
.Type
!= ec
.ContainerType
) &&
3549 ec
.ContainerType
.IsSubclassOf (InstanceExpression
.Type
)) {
3550 ErrorIsInaccesible (loc
, TypeManager
.CSharpSignature (EventInfo
));
3558 public override Expression
DoResolveLValue (EmitContext ec
, Expression right_side
)
3560 return DoResolve (ec
);
3563 public override Expression
DoResolve (EmitContext ec
)
3565 bool must_do_cs1540_check
;
3566 if (!(IsAccessorAccessible (ec
.ContainerType
, add_accessor
, out must_do_cs1540_check
) &&
3567 IsAccessorAccessible (ec
.ContainerType
, remove_accessor
, out must_do_cs1540_check
))) {
3568 ErrorIsInaccesible (loc
, TypeManager
.CSharpSignature (EventInfo
));
3572 if (!InstanceResolve (ec
, must_do_cs1540_check
))
3578 public override void Emit (EmitContext ec
)
3580 if (InstanceExpression
is This
)
3581 Report
.Error (79, loc
, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3583 Report
.Error (70, loc
, "The event `{0}' can only appear on the left hand side of += or -= "+
3584 "(except on the defining type)", Name
);
3587 public override string GetSignatureForError ()
3589 return TypeManager
.CSharpSignature (EventInfo
);
3592 public void EmitAddOrRemove (EmitContext ec
, Expression source
)
3594 BinaryDelegate source_del
= (BinaryDelegate
) source
;
3595 Expression handler
= source_del
.Right
;
3597 Argument arg
= new Argument (handler
, Argument
.AType
.Expression
);
3598 ArrayList args
= new ArrayList ();
3602 if (source_del
.IsAddition
)
3603 Invocation
.EmitCall (
3604 ec
, false, IsStatic
, InstanceExpression
, add_accessor
, args
, loc
);
3606 Invocation
.EmitCall (
3607 ec
, false, IsStatic
, InstanceExpression
, remove_accessor
, args
, loc
);
3612 public class TemporaryVariable
: Expression
, IMemoryLocation
3616 public TemporaryVariable (Type type
, Location loc
)
3620 eclass
= ExprClass
.Value
;
3623 public override Expression
DoResolve (EmitContext ec
)
3628 TypeExpr te
= new TypeExpression (type
, loc
);
3629 li
= ec
.CurrentBlock
.AddTemporaryVariable (te
, loc
);
3630 if (!li
.Resolve (ec
))
3633 AnonymousContainer am
= ec
.CurrentAnonymousMethod
;
3634 if ((am
!= null) && am
.IsIterator
)
3635 ec
.CaptureVariable (li
);
3640 public override void Emit (EmitContext ec
)
3642 ILGenerator ig
= ec
.ig
;
3644 if (li
.FieldBuilder
!= null) {
3645 ig
.Emit (OpCodes
.Ldarg_0
);
3646 ig
.Emit (OpCodes
.Ldfld
, li
.FieldBuilder
);
3648 ig
.Emit (OpCodes
.Ldloc
, li
.LocalBuilder
);
3652 public void EmitLoadAddress (EmitContext ec
)
3654 ILGenerator ig
= ec
.ig
;
3656 if (li
.FieldBuilder
!= null) {
3657 ig
.Emit (OpCodes
.Ldarg_0
);
3658 ig
.Emit (OpCodes
.Ldflda
, li
.FieldBuilder
);
3660 ig
.Emit (OpCodes
.Ldloca
, li
.LocalBuilder
);
3664 public void Store (EmitContext ec
, Expression right_side
)
3666 if (li
.FieldBuilder
!= null)
3667 ec
.ig
.Emit (OpCodes
.Ldarg_0
);
3669 right_side
.Emit (ec
);
3670 if (li
.FieldBuilder
!= null) {
3671 ec
.ig
.Emit (OpCodes
.Stfld
, li
.FieldBuilder
);
3673 ec
.ig
.Emit (OpCodes
.Stloc
, li
.LocalBuilder
);
3677 public void EmitThis (EmitContext ec
)
3679 if (li
.FieldBuilder
!= null) {
3680 ec
.ig
.Emit (OpCodes
.Ldarg_0
);
3684 public void EmitStore (ILGenerator ig
)
3686 if (li
.FieldBuilder
!= null)
3687 ig
.Emit (OpCodes
.Stfld
, li
.FieldBuilder
);
3689 ig
.Emit (OpCodes
.Stloc
, li
.LocalBuilder
);
3692 public void AddressOf (EmitContext ec
, AddressOp mode
)
3694 EmitLoadAddress (ec
);