2 // method.cs: Method based declarations
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
15 using System
.Collections
.Generic
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Runtime
.CompilerServices
;
19 using System
.Runtime
.InteropServices
;
20 using System
.Security
;
21 using System
.Security
.Permissions
;
25 using XmlElement
= System
.Object
;
30 using Mono
.CompilerServices
.SymbolWriter
;
32 namespace Mono
.CSharp
{
34 public abstract class MethodCore
: InterfaceMemberBase
36 public readonly ParametersCompiled Parameters
;
37 protected ToplevelBlock block
;
38 protected MethodSpec spec
;
40 public MethodCore (DeclSpace parent
, GenericMethod generic
,
41 FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
,
42 MemberName name
, Attributes attrs
, ParametersCompiled parameters
)
43 : base (parent
, generic
, type
, mod
, allowed_mod
, name
, attrs
)
45 Parameters
= parameters
;
49 // Returns the System.Type array for the parameters of this method
51 public Type
[] ParameterTypes
{
53 return Parameters
.Types
;
57 public ParametersCompiled ParameterInfo
{
63 public ToplevelBlock Block
{
73 public CallingConventions CallingConventions
{
75 CallingConventions cc
= Parameters
.CallingConvention
;
77 if ((ModFlags
& Modifiers
.STATIC
) == 0)
78 cc
|= CallingConventions
.HasThis
;
80 // FIXME: How is `ExplicitThis' used in C#?
86 protected override bool CheckBase ()
88 // Check whether arguments were correct.
89 if (!DefineParameters (Parameters
))
92 return base.CheckBase ();
96 // Returns a string that represents the signature for this
97 // member which should be used in XML documentation.
99 public override string GetDocCommentName (DeclSpace ds
)
101 return DocUtil
.GetMethodDocCommentName (this, Parameters
, ds
);
105 // Raised (and passed an XmlElement that contains the comment)
106 // when GenerateDocComment is writing documentation expectedly.
108 // FIXME: with a few effort, it could be done with XmlReader,
109 // that means removal of DOM use.
111 internal override void OnGenerateDocComment (XmlElement el
)
113 DocUtil
.OnMethodGenerateDocComment (this, el
, Report
);
117 // Represents header string for documentation comment.
119 public override string DocCommentHeader
124 public override bool EnableOverloadChecks (MemberCore overload
)
126 if (overload
is MethodCore
|| overload
is AbstractPropertyEventMethod
) {
127 caching_flags
|= Flags
.MethodOverloadsExist
;
131 return base.EnableOverloadChecks (overload
);
134 public MethodSpec Spec
{
138 protected override bool VerifyClsCompliance ()
140 if (!base.VerifyClsCompliance ())
143 if (Parameters
.HasArglist
) {
144 Report
.Warning (3000, 1, Location
, "Methods with variable arguments are not CLS-compliant");
147 if (!AttributeTester
.IsClsCompliant (MemberType
)) {
148 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
149 GetSignatureForError ());
152 Parameters
.VerifyClsCompliance (this);
157 interface IGenericMethodDefinition
: IMemberDefinition
159 MethodInfo
MakeGenericMethod (Type
[] targs
);
162 public class MethodSpec
: MemberSpec
165 readonly AParametersCollection parameters
;
167 public MethodSpec (MemberKind kind
, IMemberDefinition details
, MethodBase info
, AParametersCollection parameters
, Modifiers modifiers
)
168 : base (kind
, details
, info
.Name
, modifiers
)
170 this.MetaInfo
= info
;
171 this.parameters
= parameters
;
174 public override Type DeclaringType
{
176 return MetaInfo
.DeclaringType
;
180 public Type
[] GetGenericArguments ()
182 return MetaInfo
.GetGenericArguments ();
185 public MethodSpec
Inflate (Type
[] targs
)
187 // TODO: Only create MethodSpec and inflate parameters, defer the call for later
188 var mb
= ((IGenericMethodDefinition
) definition
).MakeGenericMethod (targs
);
190 // TODO: Does not work on .NET
191 var par
= TypeManager
.GetParameterData (mb
);
193 return new MethodSpec (Kind
, definition
, mb
, par
, Modifiers
);
196 public bool IsAbstract
{
198 return (Modifiers
& Modifiers
.ABSTRACT
) != 0;
202 public bool IsConstructor
{
204 return MetaInfo
.IsConstructor
;
208 public bool IsGenericMethod
{
210 return MetaInfo
.IsGenericMethod
;
214 // When is virtual or abstract
215 public bool IsVirtual
{
217 return (Modifiers
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
)) != 0;
221 public MethodBase MetaInfo
{
230 public AParametersCollection Parameters
{
231 get { return parameters; }
234 public Type ReturnType
{
236 return IsConstructor
?
237 TypeManager
.void_type
: ((MethodInfo
) MetaInfo
).ReturnType
;
242 public abstract class MethodOrOperator
: MethodCore
, IMethodData
244 public MethodBuilder MethodBuilder
;
245 ReturnParameter return_attributes
;
246 Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
247 protected MethodData MethodData
;
249 static string[] attribute_targets
= new string [] { "method", "return" }
;
251 protected MethodOrOperator (DeclSpace parent
, GenericMethod generic
, FullNamedExpression type
, Modifiers mod
,
252 Modifiers allowed_mod
, MemberName name
,
253 Attributes attrs
, ParametersCompiled parameters
)
254 : base (parent
, generic
, type
, mod
, allowed_mod
, name
,
259 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
261 if (a
.Target
== AttributeTargets
.ReturnValue
) {
262 if (return_attributes
== null)
263 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
265 return_attributes
.ApplyAttributeBuilder (a
, cb
, pa
);
269 if (a
.IsInternalMethodImplAttribute
) {
270 is_external_implementation
= true;
273 if (a
.Type
== pa
.DllImport
) {
274 const Modifiers extern_static
= Modifiers
.EXTERN
| Modifiers
.STATIC
;
275 if ((ModFlags
& extern_static
) != extern_static
) {
276 Report
.Error (601, a
.Location
, "The DllImport attribute must be specified on a method marked `static' and `extern'");
278 is_external_implementation
= true;
281 if (a
.IsValidSecurityAttribute ()) {
282 if (declarative_security
== null)
283 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
284 a
.ExtractSecurityPermissionSet (declarative_security
);
288 if (MethodBuilder
!= null)
289 MethodBuilder
.SetCustomAttribute (cb
);
292 public override AttributeTargets AttributeTargets
{
294 return AttributeTargets
.Method
;
298 protected override bool CheckForDuplications ()
300 string name
= GetFullName (MemberName
);
301 if (MemberName
.IsGeneric
)
302 name
= MemberName
.MakeName (name
, MemberName
.TypeArguments
);
304 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, name
, Parameters
, Report
);
307 public virtual EmitContext
CreateEmitContext (ILGenerator ig
)
309 return new EmitContext (
310 this, ig
, MemberType
);
313 protected override bool ResolveMemberType ()
315 if (GenericMethod
!= null) {
316 MethodBuilder
= Parent
.TypeBuilder
.DefineMethod (GetFullName (MemberName
), flags
);
317 if (!GenericMethod
.Define (this))
321 return base.ResolveMemberType ();
324 public override bool Define ()
332 if (block
!= null && block
.IsIterator
&& !(Parent
is IteratorStorey
)) {
334 // Current method is turned into automatically generated
335 // wrapper which creates an instance of iterator
337 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
338 ModFlags
|= Modifiers
.DEBUGGER_HIDDEN
;
342 if (this is Operator
)
343 kind
= MemberKind
.Operator
;
344 else if (this is Destructor
)
345 kind
= MemberKind
.Destructor
;
347 kind
= MemberKind
.Method
;
349 if (IsPartialDefinition
) {
350 caching_flags
&= ~Flags
.Excluded_Undetected
;
351 caching_flags
|= Flags
.Excluded
;
353 // Add to member cache only when a partial method implementation has not been found yet
354 if ((caching_flags
& Flags
.PartialDefinitionExists
) == 0) {
355 MethodBase mb
= new PartialMethodDefinitionInfo (this);
357 spec
= new MethodSpec (kind
, this, mb
, Parameters
, ModFlags
);
358 Parent
.MemberCache
.AddMember (mb
, spec
);
359 TypeManager
.AddMethod (mb
, this);
365 MethodData
= new MethodData (
366 this, ModFlags
, flags
, this, MethodBuilder
, GenericMethod
, base_method
);
368 if (!MethodData
.Define (Parent
.PartialContainer
, GetFullName (MemberName
), Report
))
371 MethodBuilder
= MethodData
.MethodBuilder
;
373 spec
= new MethodSpec (kind
, this, MethodBuilder
, Parameters
, ModFlags
);
375 if (TypeManager
.IsGenericMethod (MethodBuilder
))
376 Parent
.MemberCache
.AddGenericMember (MethodBuilder
, this);
378 Parent
.MemberCache
.AddMember (MethodBuilder
, spec
);
383 protected override void DoMemberTypeIndependentChecks ()
385 base.DoMemberTypeIndependentChecks ();
387 CheckAbstractAndExtern (block
!= null);
389 if ((ModFlags
& Modifiers
.PARTIAL
) != 0) {
390 for (int i
= 0; i
< Parameters
.Count
; ++i
) {
391 IParameterData p
= Parameters
.FixedParameters
[i
];
392 if (p
.ModFlags
== Parameter
.Modifier
.OUT
) {
393 Report
.Error (752, Location
, "`{0}': A partial method parameters cannot use `out' modifier",
394 GetSignatureForError ());
397 if (p
.HasDefaultValue
&& IsPartialImplementation
)
398 ((Parameter
) p
).Warning_UselessOptionalParameter (Report
);
403 protected override void DoMemberTypeDependentChecks ()
405 base.DoMemberTypeDependentChecks ();
407 if (!TypeManager
.IsGenericParameter (MemberType
)) {
408 if (MemberType
.IsAbstract
&& MemberType
.IsSealed
) {
409 Report
.Error (722, Location
, Error722
, TypeManager
.CSharpName (MemberType
));
414 public override void Emit ()
416 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
417 PredefinedAttributes
.Get
.CompilerGenerated
.EmitAttribute (MethodBuilder
);
418 if ((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0)
419 PredefinedAttributes
.Get
.DebuggerHidden
.EmitAttribute (MethodBuilder
);
421 if (TypeManager
.IsDynamicType (ReturnType
)) {
422 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
423 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
425 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ReturnType
);
426 if (trans_flags
!= null) {
427 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
428 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, TypeManager
.bool_type
.MakeArrayType ())) {
429 return_attributes
= new ReturnParameter (this, MethodBuilder
, Location
);
430 return_attributes
.Builder
.SetCustomAttribute (
431 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
436 if (OptAttributes
!= null)
437 OptAttributes
.Emit ();
439 if (declarative_security
!= null) {
440 foreach (var de
in declarative_security
) {
441 MethodBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
445 if (MethodData
!= null)
446 MethodData
.Emit (Parent
);
454 protected void Error_ConditionalAttributeIsNotValid ()
456 Report
.Error (577, Location
,
457 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
458 GetSignatureForError ());
461 public bool IsPartialDefinition
{
463 return (ModFlags
& Modifiers
.PARTIAL
) != 0 && Block
== null;
467 public bool IsPartialImplementation
{
469 return (ModFlags
& Modifiers
.PARTIAL
) != 0 && Block
!= null;
473 public override string[] ValidAttributeTargets
{
475 return attribute_targets
;
479 #region IMethodData Members
481 public Type ReturnType
{
487 public MemberName MethodName
{
494 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
496 public bool IsExcluded () {
497 if ((caching_flags
& Flags
.Excluded_Undetected
) == 0)
498 return (caching_flags
& Flags
.Excluded
) != 0;
500 caching_flags
&= ~Flags
.Excluded_Undetected
;
502 if (base_method
== null) {
503 if (OptAttributes
== null)
506 Attribute
[] attrs
= OptAttributes
.SearchMulti (PredefinedAttributes
.Get
.Conditional
);
511 foreach (Attribute a
in attrs
) {
512 string condition
= a
.GetConditionalAttributeValue ();
513 if (condition
== null)
516 if (Location
.CompilationUnit
.IsConditionalDefined (condition
))
520 caching_flags
|= Flags
.Excluded
;
524 IMethodData md
= TypeManager
.GetMethod (TypeManager
.DropGenericMethodArguments (base_method
));
526 if (AttributeTester
.IsConditionalMethodExcluded (base_method
, Location
)) {
527 caching_flags
|= Flags
.Excluded
;
533 if (md
.IsExcluded ()) {
534 caching_flags
|= Flags
.Excluded
;
540 GenericMethod IMethodData
.GenericMethod
{
542 return GenericMethod
;
546 public virtual void EmitExtraSymbolInfo (SourceMethod source
)
553 public class SourceMethod
: IMethodDef
556 SourceMethodBuilder builder
;
558 protected SourceMethod (DeclSpace parent
, MethodBase method
, ICompileUnit file
)
560 this.method
= method
;
562 builder
= SymbolWriter
.OpenMethod (file
, parent
.NamespaceEntry
.SymbolFileID
, this);
566 get { return method.Name; }
571 if (method
is MethodBuilder
)
572 return ((MethodBuilder
) method
).GetToken ().Token
;
573 else if (method
is ConstructorBuilder
)
574 return ((ConstructorBuilder
) method
).GetToken ().Token
;
576 throw new NotSupportedException ();
580 public void CloseMethod ()
582 SymbolWriter
.CloseMethod ();
585 public void SetRealMethodName (string name
)
588 builder
.SetRealMethodName (name
);
591 public static SourceMethod
Create (DeclSpace parent
, MethodBase method
, Block block
)
593 if (!SymbolWriter
.HasSymbolWriter
)
598 Location start_loc
= block
.StartLocation
;
599 if (start_loc
.IsNull
)
602 ICompileUnit compile_unit
= start_loc
.CompilationUnit
;
603 if (compile_unit
== null)
606 return new SourceMethod (parent
, method
, compile_unit
);
610 public class Method
: MethodOrOperator
, IGenericMethodDefinition
613 /// Modifiers allowed in a class declaration
615 const Modifiers AllowedModifiers
=
618 Modifiers
.PROTECTED
|
629 const Modifiers AllowedInterfaceModifiers
=
630 Modifiers
.NEW
| Modifiers
.UNSAFE
;
632 Method partialMethodImplementation
;
634 public Method (DeclSpace parent
, GenericMethod generic
,
635 FullNamedExpression return_type
, Modifiers mod
,
636 MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
637 : base (parent
, generic
, return_type
, mod
,
638 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
639 name
, attrs
, parameters
)
643 protected Method (DeclSpace parent
, FullNamedExpression return_type
, Modifiers mod
, Modifiers amod
,
644 MemberName name
, ParametersCompiled parameters
, Attributes attrs
)
645 : base (parent
, null, return_type
, mod
, amod
, name
, attrs
, parameters
)
649 public override string GetSignatureForError()
651 return base.GetSignatureForError () + Parameters
.GetSignatureForError ();
654 void Error_DuplicateEntryPoint (Method b
)
656 Report
.Error (17, b
.Location
,
657 "Program `{0}' has more than one entry point defined: `{1}'",
658 CodeGen
.FileName
, b
.GetSignatureForError ());
663 if (ReturnType
!= TypeManager
.void_type
&&
664 ReturnType
!= TypeManager
.int32_type
)
667 if (Parameters
.Count
== 0)
670 if (Parameters
.Count
> 1)
673 Type t
= Parameters
.Types
[0];
674 return t
.IsArray
&& t
.GetArrayRank () == 1 &&
675 TypeManager
.GetElementType (t
) == TypeManager
.string_type
&&
676 (Parameters
[0].ModFlags
& ~Parameter
.Modifier
.PARAMS
) == Parameter
.Modifier
.NONE
;
679 public override FullNamedExpression
LookupNamespaceOrType (string name
, Location loc
, bool ignore_cs0104
)
681 TypeParameter
[] tp
= CurrentTypeParameters
;
683 TypeParameter t
= TypeParameter
.FindTypeParameter (tp
, name
);
685 return new TypeParameterExpr (t
, loc
);
688 return base.LookupNamespaceOrType (name
, loc
, ignore_cs0104
);
691 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
693 if (a
.Type
== pa
.Conditional
) {
694 if (IsExplicitImpl
) {
695 Error_ConditionalAttributeIsNotValid ();
699 if (ReturnType
!= TypeManager
.void_type
) {
700 Report
.Error (578, Location
, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
704 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
705 Report
.Error (243, Location
, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
710 Report
.Error (582, Location
, "Conditional not valid on interface members");
714 if (MethodData
.implementing
!= null) {
715 Report
.SymbolRelatedToPreviousError (MethodData
.implementing
.DeclaringType
);
716 Report
.Error (629, Location
, "Conditional member `{0}' cannot implement interface member `{1}'",
717 GetSignatureForError (), TypeManager
.CSharpSignature (MethodData
.implementing
));
721 for (int i
= 0; i
< Parameters
.Count
; ++i
) {
722 if (Parameters
.FixedParameters
[i
].ModFlags
== Parameter
.Modifier
.OUT
) {
723 Report
.Error (685, Location
, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
729 if (a
.Type
== pa
.Extension
) {
730 a
.Error_MisusedExtensionAttribute ();
734 base.ApplyAttributeBuilder (a
, cb
, pa
);
737 protected override bool CheckForDuplications ()
739 if (!base.CheckForDuplications ())
742 var ar
= Parent
.PartialContainer
.Properties
;
744 for (int i
= 0; i
< ar
.Count
; ++i
) {
745 PropertyBase pb
= (PropertyBase
) ar
[i
];
746 if (pb
.AreAccessorsDuplicateImplementation (this))
751 ar
= Parent
.PartialContainer
.Indexers
;
753 for (int i
= 0; i
< ar
.Count
; ++i
) {
754 PropertyBase pb
= (PropertyBase
) ar
[i
];
755 if (pb
.AreAccessorsDuplicateImplementation (this))
763 protected override bool CheckBase ()
765 if (!base.CheckBase ())
768 if (base_method
!= null && (ModFlags
& Modifiers
.OVERRIDE
) != 0 && Name
== Destructor
.MetadataName
) {
769 Report
.Error (249, Location
, "Do not override `{0}'. Use destructor syntax instead",
770 TypeManager
.CSharpSignature (base_method
));
776 public override TypeParameter
[] CurrentTypeParameters
{
778 if (GenericMethod
!= null)
779 return GenericMethod
.CurrentTypeParameters
;
788 public override bool Define ()
790 if (type_name
== TypeManager
.system_void_expr
&& Parameters
.IsEmpty
&& Name
== Destructor
.MetadataName
) {
791 Report
.Warning (465, 1, Location
, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
797 if (partialMethodImplementation
!= null && IsPartialDefinition
)
798 MethodBuilder
= partialMethodImplementation
.MethodBuilder
;
800 if (RootContext
.StdLib
&& TypeManager
.IsSpecialType (ReturnType
)) {
801 Error1599 (Location
, ReturnType
, Report
);
805 if (base_method
!= null && (ModFlags
& Modifiers
.NEW
) == 0) {
806 if (Parameters
.Count
== 1 && ParameterTypes
[0] == TypeManager
.object_type
&& Name
== "Equals")
807 Parent
.PartialContainer
.Mark_HasEquals ();
808 else if (Parameters
.IsEmpty
&& Name
== "GetHashCode")
809 Parent
.PartialContainer
.Mark_HasGetHashCode ();
812 if ((ModFlags
& Modifiers
.STATIC
) == 0)
815 if (Parameters
.HasExtensionMethodType
) {
816 if (Parent
.PartialContainer
.IsStaticClass
&& !Parent
.IsGeneric
) {
817 if (!Parent
.IsTopLevel
)
818 Report
.Error (1109, Location
, "`{0}': Extension methods cannot be defined in a nested class",
819 GetSignatureForError ());
821 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Extension
;
823 Report
.Error (1110, Location
,
824 "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
825 GetSignatureForError ());
828 ModFlags
|= Modifiers
.METHOD_EXTENSION
;
829 Parent
.PartialContainer
.ModFlags
|= Modifiers
.METHOD_EXTENSION
;
830 CodeGen
.Assembly
.HasExtensionMethods
= true;
832 Report
.Error (1106, Location
, "`{0}': Extension methods must be defined in a non-generic static class",
833 GetSignatureForError ());
838 // This is used to track the Entry Point,
840 if (RootContext
.NeedsEntryPoint
&&
842 (RootContext
.MainClass
== null ||
843 RootContext
.MainClass
== Parent
.TypeBuilder
.FullName
)){
844 if (IsEntryPoint ()) {
846 if (RootContext
.EntryPoint
== null) {
847 if (Parent
.IsGeneric
|| MemberName
.IsGeneric
) {
848 Report
.Warning (402, 4, Location
, "`{0}': an entry point cannot be generic or in a generic type",
849 GetSignatureForError ());
852 RootContext
.EntryPoint
= this;
855 Error_DuplicateEntryPoint (RootContext
.EntryPoint
);
856 Error_DuplicateEntryPoint (this);
859 Report
.Warning (28, 4, Location
, "`{0}' has the wrong signature to be an entry point",
860 GetSignatureForError ());
870 public override void Emit ()
873 Report
.Debug (64, "METHOD EMIT", this, MethodBuilder
, Location
, Block
, MethodData
);
874 if (IsPartialDefinition
) {
876 // Use partial method implementation builder for partial method declaration attributes
878 if (partialMethodImplementation
!= null) {
879 MethodBuilder
= partialMethodImplementation
.MethodBuilder
;
882 } else if ((ModFlags
& Modifiers
.PARTIAL
) != 0 && (caching_flags
& Flags
.PartialDefinitionExists
) == 0) {
883 Report
.Error (759, Location
, "A partial method `{0}' implementation is missing a partial method declaration",
884 GetSignatureForError ());
889 if ((ModFlags
& Modifiers
.METHOD_EXTENSION
) != 0)
890 PredefinedAttributes
.Get
.Extension
.EmitAttribute (MethodBuilder
);
892 Console
.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
893 Location
, MethodBuilder
);
898 public override bool EnableOverloadChecks (MemberCore overload
)
900 // TODO: It can be deleted when members will be defined in correct order
901 if (overload
is Operator
)
902 return overload
.EnableOverloadChecks (this);
904 if (overload
is Indexer
)
907 return base.EnableOverloadChecks (overload
);
910 public static void Error1599 (Location loc
, Type t
, Report Report
)
912 Report
.Error (1599, loc
, "Method or delegate cannot return type `{0}'", TypeManager
.CSharpName (t
));
915 protected override MethodInfo
FindOutBaseMethod (ref Type base_ret_type
)
917 MethodInfo mi
= (MethodInfo
) Parent
.PartialContainer
.BaseCache
.FindMemberToOverride (
918 Parent
.TypeBuilder
, Name
, Parameters
, GenericMethod
, false);
923 if (mi
.IsSpecialName
)
926 base_ret_type
= TypeManager
.TypeToCoreType (mi
.ReturnType
);
930 public MethodInfo
MakeGenericMethod (Type
[] targs
)
932 return MethodBuilder
.MakeGenericMethod (targs
);
935 public void SetPartialDefinition (Method methodDefinition
)
937 caching_flags
|= Flags
.PartialDefinitionExists
;
938 methodDefinition
.partialMethodImplementation
= this;
940 // Ensure we are always using method declaration parameters
941 for (int i
= 0; i
< methodDefinition
.Parameters
.Count
; ++i
) {
942 Parameters
[i
].Name
= methodDefinition
.Parameters
[i
].Name
;
943 Parameters
[i
].DefaultValue
= methodDefinition
.Parameters
[i
].DefaultValue
;
946 if (methodDefinition
.attributes
== null)
949 if (attributes
== null) {
950 attributes
= methodDefinition
.attributes
;
952 attributes
.Attrs
.AddRange (methodDefinition
.attributes
.Attrs
);
956 protected override bool VerifyClsCompliance ()
958 if (!base.VerifyClsCompliance ())
961 if (!Parameters
.IsEmpty
) {
962 var al
= Parent
.PartialContainer
.MemberCache
.Members
[Name
];
964 MemberCache
.VerifyClsParameterConflict (al
, this, MethodBuilder
, Report
);
971 public abstract class ConstructorInitializer
: ExpressionStatement
973 Arguments argument_list
;
974 MethodGroupExpr base_constructor_group
;
976 public ConstructorInitializer (Arguments argument_list
, Location loc
)
978 this.argument_list
= argument_list
;
982 public Arguments Arguments
{
984 return argument_list
;
988 public override Expression
CreateExpressionTree (ResolveContext ec
)
990 throw new NotSupportedException ("ET");
993 protected override Expression
DoResolve (ResolveContext ec
)
995 eclass
= ExprClass
.Value
;
997 // TODO: ec.GetSignatureForError ()
998 ConstructorBuilder caller_builder
= ((Constructor
) ec
.MemberContext
).ConstructorBuilder
;
1000 if (argument_list
!= null) {
1004 // Spec mandates that constructor initializer will not have `this' access
1006 using (ec
.Set (ResolveContext
.Options
.BaseInitializer
)) {
1007 argument_list
.Resolve (ec
, out dynamic);
1011 ec
.Report
.Error (1975, loc
,
1012 "The constructor call cannot be dynamically dispatched within constructor initializer");
1018 type
= ec
.CurrentType
;
1019 if (this is ConstructorBaseInitializer
) {
1020 if (ec
.CurrentType
.BaseType
== null)
1023 type
= ec
.CurrentType
.BaseType
;
1024 if (TypeManager
.IsStruct (ec
.CurrentType
)) {
1025 ec
.Report
.Error (522, loc
,
1026 "`{0}': Struct constructors cannot call base constructors", TypeManager
.CSharpSignature (caller_builder
));
1031 // It is legal to have "this" initializers that take no arguments
1032 // in structs, they are just no-ops.
1034 // struct D { public D (int a) : this () {}
1036 if (TypeManager
.IsStruct (ec
.CurrentType
) && argument_list
== null)
1040 base_constructor_group
= MemberLookupFinal (
1041 ec
, null, type
, ConstructorBuilder
.ConstructorName
, MemberTypes
.Constructor
,
1042 BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
,
1043 loc
) as MethodGroupExpr
;
1045 if (base_constructor_group
== null)
1048 base_constructor_group
= base_constructor_group
.OverloadResolve (
1049 ec
, ref argument_list
, false, loc
);
1051 if (base_constructor_group
== null)
1055 base_constructor_group
.InstanceExpression
= ec
.GetThis (loc
);
1057 var base_ctor
= base_constructor_group
.BestCandidate
;
1059 if (base_ctor
.MetaInfo
== caller_builder
){
1060 ec
.Report
.Error (516, loc
, "Constructor `{0}' cannot call itself", TypeManager
.CSharpSignature (caller_builder
));
1066 public override void Emit (EmitContext ec
)
1068 // It can be null for static initializers
1069 if (base_constructor_group
== null)
1074 base_constructor_group
.EmitCall (ec
, argument_list
);
1077 public override void EmitStatement (EmitContext ec
)
1083 public class ConstructorBaseInitializer
: ConstructorInitializer
{
1084 public ConstructorBaseInitializer (Arguments argument_list
, Location l
) :
1085 base (argument_list
, l
)
1090 class GeneratedBaseInitializer
: ConstructorBaseInitializer
{
1091 public GeneratedBaseInitializer (Location loc
):
1097 public class ConstructorThisInitializer
: ConstructorInitializer
{
1098 public ConstructorThisInitializer (Arguments argument_list
, Location l
) :
1099 base (argument_list
, l
)
1104 public class Constructor
: MethodCore
, IMethodData
{
1105 public ConstructorBuilder ConstructorBuilder
;
1106 public ConstructorInitializer Initializer
;
1107 Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
1108 bool has_compliant_args
;
1111 // Modifiers allowed for a constructor.
1113 public const Modifiers AllowedModifiers
=
1115 Modifiers
.PROTECTED
|
1116 Modifiers
.INTERNAL
|
1122 static readonly string[] attribute_targets
= new string [] { "method" }
;
1125 // The spec claims that static is not permitted, but
1126 // my very own code has static constructors.
1128 public Constructor (DeclSpace parent
, string name
, Modifiers mod
, Attributes attrs
, ParametersCompiled args
,
1129 ConstructorInitializer init
, Location loc
)
1130 : base (parent
, null, null, mod
, AllowedModifiers
,
1131 new MemberName (name
, loc
), attrs
, args
)
1136 public bool HasCompliantArgs
{
1137 get { return has_compliant_args; }
1140 public override AttributeTargets AttributeTargets
{
1141 get { return AttributeTargets.Constructor; }
1145 // Returns true if this is a default constructor
1147 public bool IsDefault ()
1149 if ((ModFlags
& Modifiers
.STATIC
) != 0)
1150 return Parameters
.IsEmpty
;
1152 return Parameters
.IsEmpty
&&
1153 (Initializer
is ConstructorBaseInitializer
) &&
1154 (Initializer
.Arguments
== null);
1157 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1159 if (a
.IsValidSecurityAttribute ()) {
1160 if (declarative_security
== null) {
1161 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
1163 a
.ExtractSecurityPermissionSet (declarative_security
);
1167 if (a
.IsInternalMethodImplAttribute
) {
1168 is_external_implementation
= true;
1171 ConstructorBuilder
.SetCustomAttribute (cb
);
1174 protected override bool CheckBase ()
1176 if ((ModFlags
& Modifiers
.STATIC
) != 0) {
1177 if (!Parameters
.IsEmpty
) {
1178 Report
.Error (132, Location
, "`{0}': The static constructor must be parameterless",
1179 GetSignatureForError ());
1183 // the rest can be ignored
1187 // Check whether arguments were correct.
1188 if (!DefineParameters (Parameters
))
1191 if ((caching_flags
& Flags
.MethodOverloadsExist
) != 0)
1192 Parent
.MemberCache
.CheckExistingMembersOverloads (this, ConstructorInfo
.ConstructorName
,
1193 Parameters
, Report
);
1195 if (Parent
.PartialContainer
.Kind
== MemberKind
.Struct
) {
1196 if (Parameters
.Count
== 0) {
1197 Report
.Error (568, Location
,
1198 "Structs cannot contain explicit parameterless constructors");
1203 CheckProtectedModifier ();
1209 // Creates the ConstructorBuilder
1211 public override bool Define ()
1213 if (ConstructorBuilder
!= null)
1216 MethodAttributes ca
= (MethodAttributes
.RTSpecialName
|
1217 MethodAttributes
.SpecialName
);
1219 if ((ModFlags
& Modifiers
.STATIC
) != 0) {
1220 ca
|= MethodAttributes
.Static
| MethodAttributes
.Private
;
1222 ca
|= MethodAttributes
.HideBySig
;
1224 if ((ModFlags
& Modifiers
.PUBLIC
) != 0)
1225 ca
|= MethodAttributes
.Public
;
1226 else if ((ModFlags
& Modifiers
.PROTECTED
) != 0){
1227 if ((ModFlags
& Modifiers
.INTERNAL
) != 0)
1228 ca
|= MethodAttributes
.FamORAssem
;
1230 ca
|= MethodAttributes
.Family
;
1231 } else if ((ModFlags
& Modifiers
.INTERNAL
) != 0)
1232 ca
|= MethodAttributes
.Assembly
;
1234 ca
|= MethodAttributes
.Private
;
1237 if (!CheckAbstractAndExtern (block
!= null))
1240 // Check if arguments were correct.
1244 ConstructorBuilder
= Parent
.TypeBuilder
.DefineConstructor (
1245 ca
, CallingConventions
,
1246 Parameters
.GetEmitTypes ());
1248 spec
= new MethodSpec (MemberKind
.Constructor
, this, ConstructorBuilder
, Parameters
, ModFlags
);
1250 if (Parent
.PartialContainer
.IsComImport
) {
1251 if (!IsDefault ()) {
1252 Report
.Error (669, Location
, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1253 Parent
.GetSignatureForError ());
1255 ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.InternalCall
);
1258 Parent
.MemberCache
.AddMember (ConstructorBuilder
, spec
);
1259 TypeManager
.AddMethod (ConstructorBuilder
, this);
1261 // It's here only to report an error
1262 if (block
!= null && block
.IsIterator
) {
1263 member_type
= TypeManager
.void_type
;
1264 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
1273 public override void Emit ()
1275 if ((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0)
1276 PredefinedAttributes
.Get
.DebuggerHidden
.EmitAttribute (ConstructorBuilder
);
1278 if (OptAttributes
!= null)
1279 OptAttributes
.Emit ();
1284 // If we use a "this (...)" constructor initializer, then
1285 // do not emit field initializers, they are initialized in the other constructor
1287 bool emit_field_initializers
= ((ModFlags
& Modifiers
.STATIC
) != 0) ||
1288 !(Initializer
is ConstructorThisInitializer
);
1290 BlockContext bc
= new BlockContext (this, block
, TypeManager
.void_type
);
1291 bc
.Set (ResolveContext
.Options
.ConstructorScope
);
1293 if (emit_field_initializers
)
1294 Parent
.PartialContainer
.ResolveFieldInitializers (bc
);
1296 if (block
!= null) {
1297 // If this is a non-static `struct' constructor and doesn't have any
1298 // initializer, it must initialize all of the struct's fields.
1299 if ((Parent
.PartialContainer
.Kind
== MemberKind
.Struct
) &&
1300 ((ModFlags
& Modifiers
.STATIC
) == 0) && (Initializer
== null))
1301 block
.AddThisVariable (Parent
, Location
);
1303 if (block
!= null && (ModFlags
& Modifiers
.STATIC
) == 0){
1304 if (Parent
.PartialContainer
.Kind
== MemberKind
.Class
&& Initializer
== null)
1305 Initializer
= new GeneratedBaseInitializer (Location
);
1307 if (Initializer
!= null) {
1308 block
.AddScopeStatement (new StatementExpression (Initializer
));
1313 Parameters
.ApplyAttributes (ConstructorBuilder
);
1315 SourceMethod source
= SourceMethod
.Create (Parent
, ConstructorBuilder
, block
);
1317 if (block
!= null) {
1318 if (block
.Resolve (null, bc
, Parameters
, this)) {
1319 EmitContext ec
= new EmitContext (this, ConstructorBuilder
.GetILGenerator (), bc
.ReturnType
);
1320 ec
.With (EmitContext
.Options
.ConstructorScope
, true);
1322 if (!ec
.HasReturnLabel
&& bc
.HasReturnLabel
) {
1323 ec
.ReturnLabel
= bc
.ReturnLabel
;
1324 ec
.HasReturnLabel
= true;
1332 source
.CloseMethod ();
1334 if (declarative_security
!= null) {
1335 foreach (var de
in declarative_security
) {
1336 ConstructorBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
1343 // Is never override
1344 protected override MethodInfo
FindOutBaseMethod (ref Type base_ret_type
)
1349 public override string GetSignatureForError()
1351 return base.GetSignatureForError () + Parameters
.GetSignatureForError ();
1354 public override string[] ValidAttributeTargets
{
1356 return attribute_targets
;
1360 protected override bool VerifyClsCompliance ()
1362 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1366 if (!Parameters
.IsEmpty
) {
1367 var al
= Parent
.MemberCache
.Members
[ConstructorInfo
.ConstructorName
];
1369 MemberCache
.VerifyClsParameterConflict (al
, this, ConstructorBuilder
, Report
);
1371 if (TypeManager
.IsSubclassOf (Parent
.TypeBuilder
, TypeManager
.attribute_type
)) {
1372 foreach (Type param
in Parameters
.Types
) {
1373 if (param
.IsArray
) {
1379 has_compliant_args
= true;
1383 #region IMethodData Members
1385 public MemberName MethodName
{
1391 public Type ReturnType
{
1397 public EmitContext
CreateEmitContext (ILGenerator ig
)
1399 throw new NotImplementedException ();
1402 public bool IsExcluded()
1407 GenericMethod IMethodData
.GenericMethod
{
1413 void IMethodData
.EmitExtraSymbolInfo (SourceMethod source
)
1420 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1422 public interface IMethodData
1424 CallingConventions CallingConventions { get; }
1425 Location Location { get; }
1426 MemberName MethodName { get; }
1427 Type ReturnType { get; }
1428 GenericMethod GenericMethod { get; }
1429 ParametersCompiled ParameterInfo { get; }
1431 Attributes OptAttributes { get; }
1432 ToplevelBlock Block { get; set; }
1434 EmitContext
CreateEmitContext (ILGenerator ig
);
1435 ObsoleteAttribute
GetObsoleteAttribute ();
1436 string GetSignatureForError ();
1438 bool IsClsComplianceRequired ();
1440 void EmitExtraSymbolInfo (SourceMethod source
);
1444 // Encapsulates most of the Method's state
1446 public class MethodData
{
1447 static FieldInfo methodbuilder_attrs_field
;
1448 public readonly IMethodData method
;
1450 public readonly GenericMethod GenericMethod
;
1453 // Are we implementing an interface ?
1455 public MethodInfo implementing
;
1460 protected InterfaceMemberBase member
;
1461 protected Modifiers modifiers
;
1462 protected MethodAttributes flags
;
1463 protected Type declaring_type
;
1464 protected MethodInfo parent_method
;
1466 MethodBuilder builder
= null;
1467 public MethodBuilder MethodBuilder
{
1473 public Type DeclaringType
{
1475 return declaring_type
;
1479 public MethodData (InterfaceMemberBase member
,
1480 Modifiers modifiers
, MethodAttributes flags
, IMethodData method
)
1482 this.member
= member
;
1483 this.modifiers
= modifiers
;
1486 this.method
= method
;
1489 public MethodData (InterfaceMemberBase member
,
1490 Modifiers modifiers
, MethodAttributes flags
,
1491 IMethodData method
, MethodBuilder builder
,
1492 GenericMethod generic
, MethodInfo parent_method
)
1493 : this (member
, modifiers
, flags
, method
)
1495 this.builder
= builder
;
1496 this.GenericMethod
= generic
;
1497 this.parent_method
= parent_method
;
1500 public bool Define (DeclSpace parent
, string method_full_name
, Report Report
)
1502 string name
= method
.MethodName
.Basename
;
1504 TypeContainer container
= parent
.PartialContainer
;
1506 PendingImplementation pending
= container
.PendingImplementations
;
1507 if (pending
!= null){
1508 implementing
= pending
.IsInterfaceMethod (name
, member
.InterfaceType
, this);
1510 if (member
.InterfaceType
!= null){
1511 if (implementing
== null){
1512 if (member
is PropertyBase
) {
1513 Report
.Error (550, method
.Location
, "`{0}' is an accessor not found in interface member `{1}{2}'",
1514 method
.GetSignatureForError (), TypeManager
.CSharpName (member
.InterfaceType
),
1515 member
.GetSignatureForError ().Substring (member
.GetSignatureForError ().LastIndexOf ('.')));
1518 Report
.Error (539, method
.Location
,
1519 "`{0}.{1}' in explicit interface declaration is not a member of interface",
1520 TypeManager
.CSharpName (member
.InterfaceType
), member
.ShortName
);
1524 if (implementing
.IsSpecialName
&& !(method
is AbstractPropertyEventMethod
)) {
1525 Report
.SymbolRelatedToPreviousError (implementing
);
1526 Report
.Error (683, method
.Location
, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1527 member
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
));
1531 if (implementing
!= null) {
1532 AbstractPropertyEventMethod prop_method
= method
as AbstractPropertyEventMethod
;
1533 if (prop_method
== null) {
1534 if (TypeManager
.IsSpecialMethod (implementing
)) {
1535 Report
.SymbolRelatedToPreviousError (implementing
);
1536 Report
.Error (470, method
.Location
, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
1537 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
),
1538 implementing
.Name
.StartsWith ("get_") ? "get" : "set");
1540 } else if (implementing
.DeclaringType
.IsInterface
) {
1541 if (!implementing
.IsSpecialName
) {
1542 Report
.SymbolRelatedToPreviousError (implementing
);
1543 Report
.Error (686, method
.Location
, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1544 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
), container
.GetSignatureForError ());
1547 PropertyBase
.PropertyMethod pm
= prop_method
as PropertyBase
.PropertyMethod
;
1548 if (pm
!= null && pm
.HasCustomAccessModifier
&& (pm
.ModFlags
& Modifiers
.PUBLIC
) == 0) {
1549 Report
.SymbolRelatedToPreviousError (implementing
);
1550 Report
.Error (277, method
.Location
, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1551 method
.GetSignatureForError (), TypeManager
.CSharpSignature (implementing
, true));
1560 // For implicit implementations, make sure we are public, for
1561 // explicit implementations, make sure we are private.
1563 if (implementing
!= null){
1565 // Setting null inside this block will trigger a more
1566 // verbose error reporting for missing interface implementations
1568 // The "candidate" function has been flagged already
1569 // but it wont get cleared
1571 if (member
.IsExplicitImpl
){
1572 if (method
.ParameterInfo
.HasParams
&& !TypeManager
.GetParameterData (implementing
).HasParams
) {
1573 Report
.SymbolRelatedToPreviousError (implementing
);
1574 Report
.Error (466, method
.Location
, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1575 method
.GetSignatureForError ());
1579 if (implementing
.DeclaringType
.IsInterface
) {
1581 // If this is an interface method implementation,
1582 // check for public accessibility
1584 if ((flags
& MethodAttributes
.MemberAccessMask
) != MethodAttributes
.Public
)
1586 implementing
= null;
1588 } else if ((flags
& MethodAttributes
.MemberAccessMask
) == MethodAttributes
.Private
){
1589 // We may never be private.
1590 implementing
= null;
1592 } else if ((modifiers
& Modifiers
.OVERRIDE
) == 0){
1594 // We may be protected if we're overriding something.
1596 implementing
= null;
1601 // Static is not allowed
1603 if ((modifiers
& Modifiers
.STATIC
) != 0){
1604 implementing
= null;
1609 // If implementing is still valid, set flags
1611 if (implementing
!= null){
1613 // When implementing interface methods, set NewSlot
1614 // unless, we are overwriting a method.
1616 if (implementing
.DeclaringType
.IsInterface
){
1617 if ((modifiers
& Modifiers
.OVERRIDE
) == 0)
1618 flags
|= MethodAttributes
.NewSlot
;
1621 MethodAttributes
.Virtual
|
1622 MethodAttributes
.HideBySig
;
1624 // Set Final unless we're virtual, abstract or already overriding a method.
1625 if ((modifiers
& (Modifiers
.VIRTUAL
| Modifiers
.ABSTRACT
| Modifiers
.OVERRIDE
)) == 0)
1626 flags
|= MethodAttributes
.Final
;
1629 DefineMethodBuilder (container
, method_full_name
, method
.ParameterInfo
);
1631 if (builder
== null)
1634 if (container
.CurrentType
!= null)
1635 declaring_type
= container
.CurrentType
;
1637 declaring_type
= container
.TypeBuilder
;
1639 if (implementing
!= null && member
.IsExplicitImpl
) {
1640 container
.TypeBuilder
.DefineMethodOverride (builder
, implementing
);
1643 TypeManager
.AddMethod (builder
, method
);
1645 if (GenericMethod
!= null) {
1646 bool is_override
= member
.IsExplicitImpl
|
1647 ((modifiers
& Modifiers
.OVERRIDE
) != 0);
1649 if (implementing
!= null)
1650 parent_method
= implementing
;
1652 if (!GenericMethod
.DefineType (GenericMethod
, builder
, parent_method
, is_override
))
1661 /// Create the MethodBuilder for the method
1663 void DefineMethodBuilder (TypeContainer container
, string method_name
, ParametersCompiled param
)
1665 if (builder
== null) {
1666 builder
= container
.TypeBuilder
.DefineMethod (
1667 method_name
, flags
, method
.CallingConventions
,
1669 param
.GetEmitTypes ());
1674 // Generic method has been already defined to resolve method parameters
1675 // correctly when they use type parameters
1677 builder
.SetParameters (param
.GetEmitTypes ());
1678 builder
.SetReturnType (method
.ReturnType
);
1679 if (builder
.Attributes
!= flags
) {
1681 if (methodbuilder_attrs_field
== null)
1682 methodbuilder_attrs_field
= typeof (MethodBuilder
).GetField ("attrs", BindingFlags
.NonPublic
| BindingFlags
.Instance
);
1683 methodbuilder_attrs_field
.SetValue (builder
, flags
);
1685 container
.Compiler
.Report
.RuntimeMissingSupport (method
.Location
, "Generic method MethodAttributes");
1693 public void Emit (DeclSpace parent
)
1695 method
.ParameterInfo
.ApplyAttributes (MethodBuilder
);
1697 if (GenericMethod
!= null)
1698 GenericMethod
.EmitAttributes ();
1701 // clear the pending implementation flag
1703 if (implementing
!= null)
1704 parent
.PartialContainer
.PendingImplementations
.ImplementMethod (method
.MethodName
.Basename
,
1705 member
.InterfaceType
, this, member
.IsExplicitImpl
);
1707 SourceMethod source
= SourceMethod
.Create (parent
, MethodBuilder
, method
.Block
);
1709 ToplevelBlock block
= method
.Block
;
1710 if (block
!= null) {
1711 BlockContext bc
= new BlockContext ((IMemberContext
) method
, block
, method
.ReturnType
);
1712 if (block
.Resolve (null, bc
, method
.ParameterInfo
, method
)) {
1713 EmitContext ec
= method
.CreateEmitContext (MethodBuilder
.GetILGenerator ());
1714 if (!ec
.HasReturnLabel
&& bc
.HasReturnLabel
) {
1715 ec
.ReturnLabel
= bc
.ReturnLabel
;
1716 ec
.HasReturnLabel
= true;
1723 if (source
!= null) {
1724 method
.EmitExtraSymbolInfo (source
);
1725 source
.CloseMethod ();
1730 public class Destructor
: MethodOrOperator
1732 const Modifiers AllowedModifiers
=
1736 static readonly string[] attribute_targets
= new string [] { "method" }
;
1738 public static readonly string MetadataName
= "Finalize";
1740 public Destructor (DeclSpace parent
, Modifiers mod
, ParametersCompiled parameters
, Attributes attrs
, Location l
)
1741 : base (parent
, null, TypeManager
.system_void_expr
, mod
, AllowedModifiers
,
1742 new MemberName (MetadataName
, l
), attrs
, parameters
)
1744 ModFlags
&= ~Modifiers
.PRIVATE
;
1745 ModFlags
|= Modifiers
.PROTECTED
| Modifiers
.OVERRIDE
;
1748 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1750 if (a
.Type
== pa
.Conditional
) {
1751 Error_ConditionalAttributeIsNotValid ();
1755 base.ApplyAttributeBuilder (a
, cb
, pa
);
1758 protected override bool CheckBase ()
1760 if (!base.CheckBase ())
1763 if (Parent
.PartialContainer
.BaseCache
== null)
1766 Type base_type
= Parent
.PartialContainer
.BaseCache
.Container
.Type
;
1767 if (base_type
!= null && Block
!= null) {
1768 MethodGroupExpr method_expr
= Expression
.MethodLookup (Parent
.Module
.Compiler
, Parent
.TypeBuilder
, base_type
, MetadataName
, Location
);
1769 if (method_expr
== null)
1770 throw new NotImplementedException ();
1772 method_expr
.IsBase
= true;
1773 method_expr
.InstanceExpression
= new CompilerGeneratedThis (Parent
.TypeBuilder
, Location
);
1775 ToplevelBlock new_block
= new ToplevelBlock (Compiler
, Block
.StartLocation
);
1776 new_block
.EndLocation
= Block
.EndLocation
;
1778 Block finaly_block
= new ExplicitBlock (new_block
, Location
, Location
);
1779 Block try_block
= new Block (new_block
, block
);
1782 // 0-size arguments to avoid CS0250 error
1783 // TODO: Should use AddScopeStatement or something else which emits correct
1786 finaly_block
.AddStatement (new StatementExpression (new Invocation (method_expr
, new Arguments (0))));
1787 new_block
.AddStatement (new TryFinally (try_block
, finaly_block
, Location
));
1795 public override string GetSignatureForError ()
1797 return Parent
.GetSignatureForError () + ".~" + Parent
.MemberName
.Name
+ "()";
1800 protected override MethodInfo
FindOutBaseMethod (ref Type base_ret_type
)
1805 public override string[] ValidAttributeTargets
{
1807 return attribute_targets
;
1812 // Ooouh Martin, templates are missing here.
1813 // When it will be possible move here a lot of child code and template method type.
1814 public abstract class AbstractPropertyEventMethod
: MemberCore
, IMethodData
{
1815 protected MethodData method_data
;
1816 protected ToplevelBlock block
;
1817 protected Dictionary
<SecurityAction
, PermissionSet
> declarative_security
;
1819 // The accessor are created even if they are not wanted.
1820 // But we need them because their names are reserved.
1821 // Field says whether accessor will be emited or not
1822 public readonly bool IsDummy
;
1824 protected readonly string prefix
;
1826 ReturnParameter return_attributes
;
1828 public AbstractPropertyEventMethod (PropertyBasedMember member
, string prefix
)
1829 : base (member
.Parent
, SetupName (prefix
, member
, member
.Location
), null)
1831 this.prefix
= prefix
;
1835 public AbstractPropertyEventMethod (InterfaceMemberBase member
, Accessor accessor
,
1837 : base (member
.Parent
, SetupName (prefix
, member
, accessor
.Location
),
1838 accessor
.Attributes
)
1840 this.prefix
= prefix
;
1841 this.block
= accessor
.Block
;
1844 static MemberName
SetupName (string prefix
, InterfaceMemberBase member
, Location loc
)
1846 return new MemberName (member
.MemberName
.Left
, prefix
+ member
.ShortName
, loc
);
1849 public void UpdateName (InterfaceMemberBase member
)
1851 SetMemberName (SetupName (prefix
, member
, Location
));
1854 #region IMethodData Members
1856 public ToplevelBlock Block
{
1866 public CallingConventions CallingConventions
{
1868 return CallingConventions
.Standard
;
1872 public EmitContext
CreateEmitContext (ILGenerator ig
)
1874 return new EmitContext (this, ig
, ReturnType
);
1877 public bool IsExcluded ()
1882 GenericMethod IMethodData
.GenericMethod
{
1888 public MemberName MethodName
{
1894 public Type
[] ParameterTypes
{
1896 return ParameterInfo
.Types
;
1900 public abstract ParametersCompiled ParameterInfo { get ; }
1901 public abstract Type ReturnType { get; }
1905 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1907 if (a
.Type
== pa
.CLSCompliant
|| a
.Type
== pa
.Obsolete
|| a
.Type
== pa
.Conditional
) {
1908 Report
.Error (1667, a
.Location
,
1909 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
1910 TypeManager
.CSharpName (a
.Type
), a
.GetValidTargets ());
1914 if (a
.IsValidSecurityAttribute ()) {
1915 if (declarative_security
== null)
1916 declarative_security
= new Dictionary
<SecurityAction
, PermissionSet
> ();
1917 a
.ExtractSecurityPermissionSet (declarative_security
);
1921 if (a
.Target
== AttributeTargets
.Method
) {
1922 method_data
.MethodBuilder
.SetCustomAttribute (cb
);
1926 if (a
.Target
== AttributeTargets
.ReturnValue
) {
1927 if (return_attributes
== null)
1928 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
1930 return_attributes
.ApplyAttributeBuilder (a
, cb
, pa
);
1934 ApplyToExtraTarget (a
, cb
, pa
);
1937 protected virtual void ApplyToExtraTarget (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1939 throw new NotSupportedException ("You forgot to define special attribute target handling");
1942 // It is not supported for the accessors
1943 public sealed override bool Define()
1945 throw new NotSupportedException ();
1948 public virtual void Emit (DeclSpace parent
)
1950 method_data
.Emit (parent
);
1952 if ((ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0 && !Parent
.IsCompilerGenerated
)
1953 PredefinedAttributes
.Get
.CompilerGenerated
.EmitAttribute (method_data
.MethodBuilder
);
1954 if (((ModFlags
& Modifiers
.DEBUGGER_HIDDEN
) != 0))
1955 PredefinedAttributes
.Get
.DebuggerHidden
.EmitAttribute (method_data
.MethodBuilder
);
1957 if (TypeManager
.IsDynamicType (ReturnType
)) {
1958 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
1959 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
1961 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ReturnType
);
1962 if (trans_flags
!= null) {
1963 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
1964 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, TypeManager
.bool_type
.MakeArrayType ())) {
1965 return_attributes
= new ReturnParameter (this, method_data
.MethodBuilder
, Location
);
1966 return_attributes
.Builder
.SetCustomAttribute (
1967 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
1972 if (OptAttributes
!= null)
1973 OptAttributes
.Emit ();
1975 if (declarative_security
!= null) {
1976 foreach (var de
in declarative_security
) {
1977 method_data
.MethodBuilder
.AddDeclarativeSecurity (de
.Key
, de
.Value
);
1984 public override bool EnableOverloadChecks (MemberCore overload
)
1986 // This can only happen with indexers and it will
1987 // be catched as indexer difference
1988 if (overload
is AbstractPropertyEventMethod
)
1991 if (overload
is MethodCore
) {
1992 caching_flags
|= Flags
.MethodOverloadsExist
;
1998 public override bool IsClsComplianceRequired()
2003 public bool IsDuplicateImplementation (MethodCore method
)
2005 if (!MemberName
.Equals (method
.MemberName
))
2008 Type
[] param_types
= method
.ParameterTypes
;
2010 if (param_types
== null || param_types
.Length
!= ParameterTypes
.Length
)
2013 for (int i
= 0; i
< param_types
.Length
; i
++)
2014 if (param_types
[i
] != ParameterTypes
[i
])
2017 Report
.SymbolRelatedToPreviousError (method
);
2018 Report
.Error (82, Location
, "A member `{0}' is already reserved",
2019 method
.GetSignatureForError ());
2023 public override bool IsUsed
{
2032 public MethodSpec Spec { get; protected set; }
2035 // Represents header string for documentation comment.
2037 public override string DocCommentHeader
{
2038 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2041 void IMethodData
.EmitExtraSymbolInfo (SourceMethod source
)
2045 public class Operator
: MethodOrOperator
{
2047 const Modifiers AllowedModifiers
=
2053 public enum OpType
: byte {
2063 // Unary and Binary operators
2086 // Implicit and Explicit
2090 // Just because of enum
2094 public readonly OpType OperatorType
;
2096 static readonly string [] [] names
;
2100 names
= new string[(int)OpType
.TOP
][];
2101 names
[(int) OpType
.LogicalNot
] = new string [] { "!", "op_LogicalNot" }
;
2102 names
[(int) OpType
.OnesComplement
] = new string [] { "~", "op_OnesComplement" }
;
2103 names
[(int) OpType
.Increment
] = new string [] { "++", "op_Increment" }
;
2104 names
[(int) OpType
.Decrement
] = new string [] { "--", "op_Decrement" }
;
2105 names
[(int) OpType
.True
] = new string [] { "true", "op_True" }
;
2106 names
[(int) OpType
.False
] = new string [] { "false", "op_False" }
;
2107 names
[(int) OpType
.Addition
] = new string [] { "+", "op_Addition" }
;
2108 names
[(int) OpType
.Subtraction
] = new string [] { "-", "op_Subtraction" }
;
2109 names
[(int) OpType
.UnaryPlus
] = new string [] { "+", "op_UnaryPlus" }
;
2110 names
[(int) OpType
.UnaryNegation
] = new string [] { "-", "op_UnaryNegation" }
;
2111 names
[(int) OpType
.Multiply
] = new string [] { "*", "op_Multiply" }
;
2112 names
[(int) OpType
.Division
] = new string [] { "/", "op_Division" }
;
2113 names
[(int) OpType
.Modulus
] = new string [] { "%", "op_Modulus" }
;
2114 names
[(int) OpType
.BitwiseAnd
] = new string [] { "&", "op_BitwiseAnd" }
;
2115 names
[(int) OpType
.BitwiseOr
] = new string [] { "|", "op_BitwiseOr" }
;
2116 names
[(int) OpType
.ExclusiveOr
] = new string [] { "^", "op_ExclusiveOr" }
;
2117 names
[(int) OpType
.LeftShift
] = new string [] { "<<", "op_LeftShift" }
;
2118 names
[(int) OpType
.RightShift
] = new string [] { ">>", "op_RightShift" }
;
2119 names
[(int) OpType
.Equality
] = new string [] { "==", "op_Equality" }
;
2120 names
[(int) OpType
.Inequality
] = new string [] { "!=", "op_Inequality" }
;
2121 names
[(int) OpType
.GreaterThan
] = new string [] { ">", "op_GreaterThan" }
;
2122 names
[(int) OpType
.LessThan
] = new string [] { "<", "op_LessThan" }
;
2123 names
[(int) OpType
.GreaterThanOrEqual
] = new string [] { ">=", "op_GreaterThanOrEqual" }
;
2124 names
[(int) OpType
.LessThanOrEqual
] = new string [] { "<=", "op_LessThanOrEqual" }
;
2125 names
[(int) OpType
.Implicit
] = new string [] { "implicit", "op_Implicit" }
;
2126 names
[(int) OpType
.Explicit
] = new string [] { "explicit", "op_Explicit" }
;
2129 public Operator (DeclSpace parent
, OpType type
, FullNamedExpression ret_type
,
2130 Modifiers mod_flags
, ParametersCompiled parameters
,
2131 ToplevelBlock block
, Attributes attrs
, Location loc
)
2132 : base (parent
, null, ret_type
, mod_flags
, AllowedModifiers
,
2133 new MemberName (GetMetadataName (type
), loc
), attrs
, parameters
)
2135 OperatorType
= type
;
2139 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
2141 if (a
.Type
== pa
.Conditional
) {
2142 Error_ConditionalAttributeIsNotValid ();
2146 base.ApplyAttributeBuilder (a
, cb
, pa
);
2149 public override bool Define ()
2151 const Modifiers RequiredModifiers
= Modifiers
.PUBLIC
| Modifiers
.STATIC
;
2152 if ((ModFlags
& RequiredModifiers
) != RequiredModifiers
){
2153 Report
.Error (558, Location
, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2156 if (!base.Define ())
2159 // imlicit and explicit operator of same types are not allowed
2160 if (OperatorType
== OpType
.Explicit
)
2161 Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetMetadataName (OpType
.Implicit
), Parameters
, Report
);
2162 else if (OperatorType
== OpType
.Implicit
)
2163 Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetMetadataName (OpType
.Explicit
), Parameters
, Report
);
2165 Type declaring_type
= MethodData
.DeclaringType
;
2166 Type return_type
= MemberType
;
2167 Type first_arg_type
= ParameterTypes
[0];
2169 Type first_arg_type_unwrap
= first_arg_type
;
2170 if (TypeManager
.IsNullableType (first_arg_type
))
2171 first_arg_type_unwrap
= TypeManager
.TypeToCoreType (TypeManager
.GetTypeArguments (first_arg_type
) [0]);
2173 Type return_type_unwrap
= return_type
;
2174 if (TypeManager
.IsNullableType (return_type
))
2175 return_type_unwrap
= TypeManager
.TypeToCoreType (TypeManager
.GetTypeArguments (return_type
) [0]);
2177 if (TypeManager
.IsDynamicType (return_type
) || TypeManager
.IsDynamicType (first_arg_type
)) {
2178 Report
.Error (1964, Location
,
2179 "User-defined operator `{0}' cannot convert to or from the dynamic type",
2180 GetSignatureForError ());
2186 // Rules for conversion operators
2188 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2189 if (first_arg_type_unwrap
== return_type_unwrap
&& first_arg_type_unwrap
== declaring_type
){
2190 Report
.Error (555, Location
,
2191 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2196 if (TypeManager
.IsEqual (declaring_type
, return_type
) || declaring_type
== return_type_unwrap
) {
2197 conv_type
= first_arg_type
;
2198 } else if (TypeManager
.IsEqual (declaring_type
, first_arg_type
) || declaring_type
== first_arg_type_unwrap
) {
2199 conv_type
= return_type
;
2201 Report
.Error (556, Location
,
2202 "User-defined conversion must convert to or from the enclosing type");
2207 // Because IsInterface and IsClass are not supported
2209 if (!TypeManager
.IsGenericParameter (conv_type
)) {
2210 if (conv_type
.IsInterface
) {
2211 Report
.Error (552, Location
, "User-defined conversion `{0}' cannot convert to or from an interface type",
2212 GetSignatureForError ());
2216 if (conv_type
.IsClass
) {
2217 if (TypeManager
.IsSubclassOf (declaring_type
, conv_type
)) {
2218 Report
.Error (553, Location
, "User-defined conversion `{0}' cannot convert to or from a base class",
2219 GetSignatureForError ());
2223 if (TypeManager
.IsSubclassOf (conv_type
, declaring_type
)) {
2224 Report
.Error (554, Location
, "User-defined conversion `{0}' cannot convert to or from a derived class",
2225 GetSignatureForError ());
2230 } else if (OperatorType
== OpType
.LeftShift
|| OperatorType
== OpType
.RightShift
) {
2231 if (first_arg_type
!= declaring_type
|| Parameters
.Types
[1] != TypeManager
.int32_type
) {
2232 Report
.Error (564, Location
, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
2235 } else if (Parameters
.Count
== 1) {
2236 // Checks for Unary operators
2238 if (OperatorType
== OpType
.Increment
|| OperatorType
== OpType
.Decrement
) {
2239 if (return_type
!= declaring_type
&& !TypeManager
.IsSubclassOf (return_type
, declaring_type
)) {
2240 Report
.Error (448, Location
,
2241 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2244 if (first_arg_type
!= declaring_type
) {
2246 559, Location
, "The parameter type for ++ or -- operator must be the containing type");
2251 if (!TypeManager
.IsEqual (first_arg_type_unwrap
, declaring_type
)){
2252 Report
.Error (562, Location
,
2253 "The parameter type of a unary operator must be the containing type");
2257 if (OperatorType
== OpType
.True
|| OperatorType
== OpType
.False
) {
2258 if (return_type
!= TypeManager
.bool_type
){
2261 "The return type of operator True or False " +
2267 } else if (!TypeManager
.IsEqual (first_arg_type_unwrap
, declaring_type
)) {
2268 // Checks for Binary operators
2270 var second_arg_type
= ParameterTypes
[1];
2271 if (TypeManager
.IsNullableType (second_arg_type
))
2272 second_arg_type
= TypeManager
.TypeToCoreType (TypeManager
.GetTypeArguments (second_arg_type
) [0]);
2274 if (!TypeManager
.IsEqual (second_arg_type
, declaring_type
)) {
2275 Report
.Error (563, Location
,
2276 "One of the parameters of a binary operator must be the containing type");
2284 protected override bool ResolveMemberType ()
2286 if (!base.ResolveMemberType ())
2289 flags
|= MethodAttributes
.SpecialName
| MethodAttributes
.HideBySig
;
2293 // Operator cannot be override
2294 protected override MethodInfo
FindOutBaseMethod (ref Type base_ret_type
)
2299 public static string GetName (OpType ot
)
2301 return names
[(int) ot
] [0];
2304 public static string GetName (string metadata_name
)
2306 for (int i
= 0; i
< names
.Length
; ++i
) {
2307 if (names
[i
] [1] == metadata_name
)
2308 return names
[i
] [0];
2313 public static string GetMetadataName (OpType ot
)
2315 return names
[(int) ot
] [1];
2318 public static string GetMetadataName (string name
)
2320 for (int i
= 0; i
< names
.Length
; ++i
) {
2321 if (names
[i
] [0] == name
)
2322 return names
[i
] [1];
2327 public static OpType
? GetType (string metadata_name
)
2329 for (int i
= 0; i
< names
.Length
; ++i
) {
2330 if (names
[i
][1] == metadata_name
)
2337 public OpType
GetMatchingOperator ()
2339 switch (OperatorType
) {
2340 case OpType
.Equality
:
2341 return OpType
.Inequality
;
2342 case OpType
.Inequality
:
2343 return OpType
.Equality
;
2345 return OpType
.False
;
2348 case OpType
.GreaterThan
:
2349 return OpType
.LessThan
;
2350 case OpType
.LessThan
:
2351 return OpType
.GreaterThan
;
2352 case OpType
.GreaterThanOrEqual
:
2353 return OpType
.LessThanOrEqual
;
2354 case OpType
.LessThanOrEqual
:
2355 return OpType
.GreaterThanOrEqual
;
2361 public override string GetSignatureForError ()
2363 StringBuilder sb
= new StringBuilder ();
2364 if (OperatorType
== OpType
.Implicit
|| OperatorType
== OpType
.Explicit
) {
2365 sb
.AppendFormat ("{0}.{1} operator {2}",
2366 Parent
.GetSignatureForError (), GetName (OperatorType
), type_name
.GetSignatureForError ());
2369 sb
.AppendFormat ("{0}.operator {1}", Parent
.GetSignatureForError (), GetName (OperatorType
));
2372 sb
.Append (Parameters
.GetSignatureForError ());
2373 return sb
.ToString ();
2378 // This is used to compare method signatures
2380 struct MethodSignature
{
2382 public Type RetType
;
2383 public Type
[] Parameters
;
2386 /// This delegate is used to extract methods which have the
2387 /// same signature as the argument
2389 public static MemberFilter method_signature_filter
= new MemberFilter (MemberSignatureCompare
);
2391 public MethodSignature (string name
, Type ret_type
, Type
[] parameters
)
2396 if (parameters
== null)
2397 Parameters
= Type
.EmptyTypes
;
2399 Parameters
= parameters
;
2402 public override string ToString ()
2405 if (Parameters
.Length
!= 0){
2406 System
.Text
.StringBuilder sb
= new System
.Text
.StringBuilder ();
2407 for (int i
= 0; i
< Parameters
.Length
; i
++){
2408 sb
.Append (Parameters
[i
]);
2409 if (i
+1 < Parameters
.Length
)
2412 pars
= sb
.ToString ();
2415 return String
.Format ("{0} {1} ({2})", RetType
, Name
, pars
);
2418 public override int GetHashCode ()
2420 return Name
.GetHashCode ();
2423 public override bool Equals (Object o
)
2425 MethodSignature other
= (MethodSignature
) o
;
2427 if (other
.Name
!= Name
)
2430 if (other
.RetType
!= RetType
)
2433 if (Parameters
== null){
2434 if (other
.Parameters
== null)
2439 if (other
.Parameters
== null)
2442 int c
= Parameters
.Length
;
2443 if (other
.Parameters
.Length
!= c
)
2446 for (int i
= 0; i
< c
; i
++)
2447 if (other
.Parameters
[i
] != Parameters
[i
])
2453 static bool MemberSignatureCompare (MemberInfo m
, object filter_criteria
)
2455 MethodSignature sig
= (MethodSignature
) filter_criteria
;
2457 if (m
.Name
!= sig
.Name
)
2461 MethodInfo mi
= m
as MethodInfo
;
2462 PropertyInfo pi
= m
as PropertyInfo
;
2465 ReturnType
= mi
.ReturnType
;
2466 else if (pi
!= null)
2467 ReturnType
= pi
.PropertyType
;
2472 // we use sig.RetType == null to mean `do not check the
2473 // method return value.
2475 if (sig
.RetType
!= null) {
2476 if (!TypeManager
.IsEqual (ReturnType
, sig
.RetType
))
2482 args
= TypeManager
.GetParameterData (mi
).Types
;
2484 args
= TypeManager
.GetParameterData (pi
).Types
;
2485 Type
[] sigp
= sig
.Parameters
;
2487 if (args
.Length
!= sigp
.Length
)
2490 for (int i
= args
.Length
- 1; i
>= 0; i
--)
2491 if (!TypeManager
.IsEqual (args
[i
], sigp
[i
]))