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 (IMemberDefinition details, MethodBase info, AParametersCollection parameters, Modifiers modifiers)
168 : base (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 (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;
341 if (IsPartialDefinition) {
342 caching_flags &= ~Flags.Excluded_Undetected;
343 caching_flags |= Flags.Excluded;
345 // Add to member cache only when a partial method implementation has not been found yet
346 if ((caching_flags & Flags.PartialDefinitionExists) == 0) {
347 MethodBase mb = new PartialMethodDefinitionInfo (this);
348 Parent.MemberCache.AddMember (mb, this);
349 TypeManager.AddMethod (mb, this);
351 spec = new MethodSpec (this, mb, Parameters, ModFlags);
357 MethodData = new MethodData (
358 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
360 if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report))
363 MethodBuilder = MethodData.MethodBuilder;
365 spec = new MethodSpec (this, MethodBuilder, Parameters, ModFlags);
367 if (TypeManager.IsGenericMethod (MethodBuilder))
368 Parent.MemberCache.AddGenericMember (MethodBuilder, this);
370 Parent.MemberCache.AddMember (MethodBuilder, this);
375 protected override void DoMemberTypeIndependentChecks ()
377 base.DoMemberTypeIndependentChecks ();
379 CheckAbstractAndExtern (block != null);
381 if ((ModFlags & Modifiers.PARTIAL) != 0) {
382 for (int i = 0; i < Parameters.Count; ++i) {
383 IParameterData p = Parameters.FixedParameters [i];
384 if (p.ModFlags == Parameter.Modifier.OUT) {
385 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
386 GetSignatureForError ());
389 if (p.HasDefaultValue && IsPartialImplementation)
390 ((Parameter) p).Warning_UselessOptionalParameter (Report);
395 protected override void DoMemberTypeDependentChecks ()
397 base.DoMemberTypeDependentChecks ();
399 if (!TypeManager.IsGenericParameter (MemberType)) {
400 if (MemberType.IsAbstract && MemberType.IsSealed) {
401 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
406 public override void Emit ()
408 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
409 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder);
410 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
411 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder);
413 if (TypeManager.IsDynamicType (ReturnType)) {
414 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
415 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
417 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
418 if (trans_flags != null) {
419 var pa = PredefinedAttributes.Get.DynamicTransform;
420 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
421 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
422 return_attributes.Builder.SetCustomAttribute (
423 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
428 if (OptAttributes != null)
429 OptAttributes.Emit ();
431 if (declarative_security != null) {
432 foreach (var de in declarative_security) {
433 MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
437 if (MethodData != null)
438 MethodData.Emit (Parent);
446 protected void Error_ConditionalAttributeIsNotValid ()
448 Report.Error (577, Location,
449 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
450 GetSignatureForError ());
453 public bool IsPartialDefinition {
455 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
459 public bool IsPartialImplementation {
461 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
465 public override string[] ValidAttributeTargets {
467 return attribute_targets;
471 #region IMethodData Members
473 public Type ReturnType {
479 public MemberName MethodName {
486 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
488 public bool IsExcluded () {
489 if ((caching_flags & Flags.Excluded_Undetected) == 0)
490 return (caching_flags & Flags.Excluded) != 0;
492 caching_flags &= ~Flags.Excluded_Undetected;
494 if (base_method == null) {
495 if (OptAttributes == null)
498 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
503 foreach (Attribute a in attrs) {
504 string condition = a.GetConditionalAttributeValue ();
505 if (condition == null)
508 if (Location.CompilationUnit.IsConditionalDefined (condition))
512 caching_flags |= Flags.Excluded;
516 IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
518 if (AttributeTester.IsConditionalMethodExcluded (base_method, Location)) {
519 caching_flags |= Flags.Excluded;
525 if (md.IsExcluded ()) {
526 caching_flags |= Flags.Excluded;
532 GenericMethod IMethodData.GenericMethod {
534 return GenericMethod;
538 public virtual void EmitExtraSymbolInfo (SourceMethod source)
545 public class SourceMethod : IMethodDef
548 SourceMethodBuilder builder;
550 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
552 this.method = method;
554 builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
558 get { return method.Name; }
563 if (method is MethodBuilder)
564 return ((MethodBuilder) method).GetToken ().Token;
565 else if (method is ConstructorBuilder)
566 return ((ConstructorBuilder) method).GetToken ().Token;
568 throw new NotSupportedException ();
572 public void CloseMethod ()
574 SymbolWriter.CloseMethod ();
577 public void SetRealMethodName (string name)
580 builder.SetRealMethodName (name);
583 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
585 if (!SymbolWriter.HasSymbolWriter)
590 Location start_loc = block.StartLocation;
591 if (start_loc.IsNull)
594 ICompileUnit compile_unit = start_loc.CompilationUnit;
595 if (compile_unit == null)
598 return new SourceMethod (parent, method, compile_unit);
602 public class Method : MethodOrOperator, IGenericMethodDefinition
605 /// Modifiers allowed in a class declaration
607 const Modifiers AllowedModifiers =
610 Modifiers.PROTECTED |
621 const Modifiers AllowedInterfaceModifiers =
622 Modifiers.NEW | Modifiers.UNSAFE;
624 Method partialMethodImplementation;
626 public Method (DeclSpace parent, GenericMethod generic,
627 FullNamedExpression return_type, Modifiers mod,
628 MemberName name, ParametersCompiled parameters, Attributes attrs)
629 : base (parent, generic, return_type, mod,
630 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
631 name, attrs, parameters)
635 protected Method (DeclSpace parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
636 MemberName name, ParametersCompiled parameters, Attributes attrs)
637 : base (parent, null, return_type, mod, amod, name, attrs, parameters)
641 public override string GetSignatureForError()
643 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
646 void Error_DuplicateEntryPoint (Method b)
648 Report.Error (17, b.Location,
649 "Program `{0}' has more than one entry point defined: `{1}'",
650 CodeGen.FileName, b.GetSignatureForError ());
655 if (ReturnType != TypeManager.void_type &&
656 ReturnType != TypeManager.int32_type)
659 if (Parameters.Count == 0)
662 if (Parameters.Count > 1)
665 Type t = Parameters.Types [0];
666 return t.IsArray && t.GetArrayRank () == 1 &&
667 TypeManager.GetElementType (t) == TypeManager.string_type &&
668 (Parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
671 public override FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
673 TypeParameter[] tp = CurrentTypeParameters;
675 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
677 return new TypeParameterExpr (t, loc);
680 return base.LookupNamespaceOrType (name, loc, ignore_cs0104);
683 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
685 if (a.Type == pa.Conditional) {
686 if (IsExplicitImpl) {
687 Error_ConditionalAttributeIsNotValid ();
691 if (ReturnType != TypeManager.void_type) {
692 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
696 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
697 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
702 Report.Error (582, Location, "Conditional not valid on interface members");
706 if (MethodData.implementing != null) {
707 Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
708 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
709 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
713 for (int i = 0; i < Parameters.Count; ++i) {
714 if (Parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
715 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
721 if (a.Type == pa.Extension) {
722 a.Error_MisusedExtensionAttribute ();
726 base.ApplyAttributeBuilder (a, cb, pa);
729 protected override bool CheckForDuplications ()
731 if (!base.CheckForDuplications ())
734 var ar = Parent.PartialContainer.Properties;
736 for (int i = 0; i < ar.Count; ++i) {
737 PropertyBase pb = (PropertyBase) ar [i];
738 if (pb.AreAccessorsDuplicateImplementation (this))
743 ar = Parent.PartialContainer.Indexers;
745 for (int i = 0; i < ar.Count; ++i) {
746 PropertyBase pb = (PropertyBase) ar [i];
747 if (pb.AreAccessorsDuplicateImplementation (this))
755 protected override bool CheckBase ()
757 if (!base.CheckBase ())
760 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == Destructor.MetadataName) {
761 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
762 TypeManager.CSharpSignature (base_method));
768 public override TypeParameter[] CurrentTypeParameters {
770 if (GenericMethod != null)
771 return GenericMethod.CurrentTypeParameters;
780 public override bool Define ()
782 if (type_name == TypeManager.system_void_expr && Parameters.IsEmpty && Name == Destructor.MetadataName) {
783 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
789 if (partialMethodImplementation != null && IsPartialDefinition)
790 MethodBuilder = partialMethodImplementation.MethodBuilder;
792 if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
793 Error1599 (Location, ReturnType, Report);
797 if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
798 if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
799 Parent.PartialContainer.Mark_HasEquals ();
800 else if (Parameters.IsEmpty && Name == "GetHashCode")
801 Parent.PartialContainer.Mark_HasGetHashCode ();
804 if ((ModFlags & Modifiers.STATIC) == 0)
807 if (Parameters.HasExtensionMethodType) {
808 if (Parent.PartialContainer.IsStaticClass && !Parent.IsGeneric) {
809 if (!Parent.IsTopLevel)
810 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
811 GetSignatureForError ());
813 PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
815 Report.Error (1110, Location,
816 "`{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",
817 GetSignatureForError ());
820 ModFlags |= Modifiers.METHOD_EXTENSION;
821 Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
822 CodeGen.Assembly.HasExtensionMethods = true;
824 Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
825 GetSignatureForError ());
830 // This is used to track the Entry Point,
832 if (RootContext.NeedsEntryPoint &&
834 (RootContext.MainClass == null ||
835 RootContext.MainClass == Parent.TypeBuilder.FullName)){
836 if (IsEntryPoint ()) {
838 if (RootContext.EntryPoint == null) {
839 if (Parent.IsGeneric || MemberName.IsGeneric) {
840 Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
841 GetSignatureForError ());
844 RootContext.EntryPoint = this;
847 Error_DuplicateEntryPoint (RootContext.EntryPoint);
848 Error_DuplicateEntryPoint (this);
851 Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
852 GetSignatureForError ());
862 public override void Emit ()
865 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
866 if (IsPartialDefinition) {
868 // Use partial method implementation builder for partial method declaration attributes
870 if (partialMethodImplementation != null) {
871 MethodBuilder = partialMethodImplementation.MethodBuilder;
874 } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
875 Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
876 GetSignatureForError ());
881 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
882 PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
884 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
885 Location, MethodBuilder);
890 public override bool EnableOverloadChecks (MemberCore overload)
892 // TODO: It can be deleted when members will be defined in correct order
893 if (overload is Operator)
894 return overload.EnableOverloadChecks (this);
896 if (overload is Indexer)
899 return base.EnableOverloadChecks (overload);
902 public static void Error1599 (Location loc, Type t, Report Report)
904 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
907 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
909 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindMemberToOverride (
910 Parent.TypeBuilder, Name, Parameters, GenericMethod, false);
915 if (mi.IsSpecialName)
918 base_ret_type = TypeManager.TypeToCoreType (mi.ReturnType);
922 public MethodInfo MakeGenericMethod (Type[] targs)
924 return MethodBuilder.MakeGenericMethod (targs);
927 public void SetPartialDefinition (Method methodDefinition)
929 caching_flags |= Flags.PartialDefinitionExists;
930 methodDefinition.partialMethodImplementation = this;
932 // Ensure we are always using method declaration parameters
933 for (int i = 0; i < methodDefinition.Parameters.Count; ++i ) {
934 Parameters [i].Name = methodDefinition.Parameters [i].Name;
935 Parameters [i].DefaultValue = methodDefinition.Parameters [i].DefaultValue;
938 if (methodDefinition.attributes == null)
941 if (attributes == null) {
942 attributes = methodDefinition.attributes;
944 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
948 protected override bool VerifyClsCompliance ()
950 if (!base.VerifyClsCompliance ())
953 if (!Parameters.IsEmpty) {
954 var al = Parent.PartialContainer.MemberCache.Members [Name];
956 MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder, Report);
963 public abstract class ConstructorInitializer : ExpressionStatement
965 Arguments argument_list;
966 MethodGroupExpr base_constructor_group;
968 public ConstructorInitializer (Arguments argument_list, Location loc)
970 this.argument_list = argument_list;
974 public Arguments Arguments {
976 return argument_list;
980 public override Expression CreateExpressionTree (ResolveContext ec)
982 throw new NotSupportedException ("ET");
985 protected override Expression DoResolve (ResolveContext ec)
987 eclass = ExprClass.Value;
989 // TODO: ec.GetSignatureForError ()
990 ConstructorBuilder caller_builder = ((Constructor) ec.MemberContext).ConstructorBuilder;
992 if (argument_list != null) {
996 // Spec mandates that constructor initializer will not have `this' access
998 using (ec.Set (ResolveContext.Options.BaseInitializer)) {
999 argument_list.Resolve (ec, out dynamic);
1003 ec.Report.Error (1975, loc,
1004 "The constructor call cannot be dynamically dispatched within constructor initializer");
1010 type = ec.CurrentType;
1011 if (this is ConstructorBaseInitializer) {
1012 if (ec.CurrentType.BaseType == null)
1015 type = ec.CurrentType.BaseType;
1016 if (TypeManager.IsStruct (ec.CurrentType)) {
1017 ec.Report.Error (522, loc,
1018 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
1023 // It is legal to have "this" initializers that take no arguments
1024 // in structs, they are just no-ops.
1026 // struct D { public D (int a) : this () {}
1028 if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
1032 base_constructor_group = MemberLookupFinal (
1033 ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
1034 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
1035 loc) as MethodGroupExpr;
1037 if (base_constructor_group == null)
1040 base_constructor_group = base_constructor_group.OverloadResolve (
1041 ec, ref argument_list, false, loc);
1043 if (base_constructor_group == null)
1047 base_constructor_group.InstanceExpression = ec.GetThis (loc);
1049 var base_ctor = base_constructor_group.BestCandidate;
1051 if (base_ctor.MetaInfo == caller_builder){
1052 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
1058 public override void Emit (EmitContext ec)
1060 // It can be null for static initializers
1061 if (base_constructor_group == null)
1066 base_constructor_group.EmitCall (ec, argument_list);
1069 public override void EmitStatement (EmitContext ec)
1075 public class ConstructorBaseInitializer : ConstructorInitializer {
1076 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1077 base (argument_list, l)
1082 class GeneratedBaseInitializer: ConstructorBaseInitializer {
1083 public GeneratedBaseInitializer (Location loc):
1089 public class ConstructorThisInitializer : ConstructorInitializer {
1090 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1091 base (argument_list, l)
1096 public class Constructor : MethodCore, IMethodData {
1097 public ConstructorBuilder ConstructorBuilder;
1098 public ConstructorInitializer Initializer;
1099 Dictionary<SecurityAction, PermissionSet> declarative_security;
1100 bool has_compliant_args;
1103 // Modifiers allowed for a constructor.
1105 public const Modifiers AllowedModifiers =
1107 Modifiers.PROTECTED |
1108 Modifiers.INTERNAL |
1114 static readonly string[] attribute_targets = new string [] { "method" };
1117 // The spec claims that static is not permitted, but
1118 // my very own code has static constructors.
1120 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
1121 ConstructorInitializer init, Location loc)
1122 : base (parent, null, null, mod, AllowedModifiers,
1123 new MemberName (name, loc), attrs, args)
1128 public bool HasCompliantArgs {
1129 get { return has_compliant_args; }
1132 public override AttributeTargets AttributeTargets {
1133 get { return AttributeTargets.Constructor; }
1137 // Returns true if this is a default constructor
1139 public bool IsDefault ()
1141 if ((ModFlags & Modifiers.STATIC) != 0)
1142 return Parameters.IsEmpty;
1144 return Parameters.IsEmpty &&
1145 (Initializer is ConstructorBaseInitializer) &&
1146 (Initializer.Arguments == null);
1149 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1151 if (a.IsValidSecurityAttribute ()) {
1152 if (declarative_security == null) {
1153 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1155 a.ExtractSecurityPermissionSet (declarative_security);
1159 if (a.IsInternalMethodImplAttribute) {
1160 is_external_implementation = true;
1163 ConstructorBuilder.SetCustomAttribute (cb);
1166 protected override bool CheckBase ()
1168 if ((ModFlags & Modifiers.STATIC) != 0) {
1169 if (!Parameters.IsEmpty) {
1170 Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1171 GetSignatureForError ());
1175 // the rest can be ignored
1179 // Check whether arguments were correct.
1180 if (!DefineParameters (Parameters))
1183 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1184 Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorInfo.ConstructorName,
1185 Parameters, Report);
1187 if (Parent.PartialContainer.Kind == Kind.Struct) {
1188 if (Parameters.Count == 0) {
1189 Report.Error (568, Location,
1190 "Structs cannot contain explicit parameterless constructors");
1195 CheckProtectedModifier ();
1201 // Creates the ConstructorBuilder
1203 public override bool Define ()
1205 if (ConstructorBuilder != null)
1208 MethodAttributes ca = (MethodAttributes.RTSpecialName |
1209 MethodAttributes.SpecialName);
1211 if ((ModFlags & Modifiers.STATIC) != 0) {
1212 ca |= MethodAttributes.Static | MethodAttributes.Private;
1214 ca |= MethodAttributes.HideBySig;
1216 if ((ModFlags & Modifiers.PUBLIC) != 0)
1217 ca |= MethodAttributes.Public;
1218 else if ((ModFlags & Modifiers.PROTECTED) != 0){
1219 if ((ModFlags & Modifiers.INTERNAL) != 0)
1220 ca |= MethodAttributes.FamORAssem;
1222 ca |= MethodAttributes.Family;
1223 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
1224 ca |= MethodAttributes.Assembly;
1226 ca |= MethodAttributes.Private;
1229 if (!CheckAbstractAndExtern (block != null))
1232 // Check if arguments were correct.
1236 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1237 ca, CallingConventions,
1238 Parameters.GetEmitTypes ());
1240 spec = new MethodSpec (this, ConstructorBuilder, Parameters, ModFlags);
1242 if (Parent.PartialContainer.IsComImport) {
1243 if (!IsDefault ()) {
1244 Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1245 Parent.GetSignatureForError ());
1247 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1250 Parent.MemberCache.AddMember (ConstructorBuilder, this);
1251 TypeManager.AddMethod (ConstructorBuilder, this);
1253 // It's here only to report an error
1254 if (block != null && block.IsIterator) {
1255 member_type = TypeManager.void_type;
1256 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1265 public override void Emit ()
1267 if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1268 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1270 if (OptAttributes != null)
1271 OptAttributes.Emit ();
1276 // If we use a "this (...)" constructor initializer, then
1277 // do not emit field initializers, they are initialized in the other constructor
1279 bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1280 !(Initializer is ConstructorThisInitializer);
1282 BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
1283 bc.Set (ResolveContext.Options.ConstructorScope);
1285 if (emit_field_initializers)
1286 Parent.PartialContainer.ResolveFieldInitializers (bc);
1288 if (block != null) {
1289 // If this is a non-static `struct' constructor and doesn't have any
1290 // initializer, it must initialize all of the struct's fields.
1291 if ((Parent.PartialContainer.Kind == Kind.Struct) &&
1292 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1293 block.AddThisVariable (Parent, Location);
1295 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
1296 if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
1297 Initializer = new GeneratedBaseInitializer (Location);
1299 if (Initializer != null) {
1300 block.AddScopeStatement (new StatementExpression (Initializer));
1305 Parameters.ApplyAttributes (ConstructorBuilder);
1307 SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1309 if (block != null) {
1310 if (block.Resolve (null, bc, Parameters, this)) {
1311 EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1312 ec.With (EmitContext.Options.ConstructorScope, true);
1314 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1315 ec.ReturnLabel = bc.ReturnLabel;
1316 ec.HasReturnLabel = true;
1324 source.CloseMethod ();
1326 if (declarative_security != null) {
1327 foreach (var de in declarative_security) {
1328 ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1335 // Is never override
1336 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
1341 public override string GetSignatureForError()
1343 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
1346 public override string[] ValidAttributeTargets {
1348 return attribute_targets;
1352 protected override bool VerifyClsCompliance ()
1354 if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1358 if (!Parameters.IsEmpty) {
1359 var al = Parent.MemberCache.Members [ConstructorInfo.ConstructorName];
1361 MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder, Report);
1363 if (TypeManager.IsSubclassOf (Parent.TypeBuilder, TypeManager.attribute_type)) {
1364 foreach (Type param in Parameters.Types) {
1365 if (param.IsArray) {
1371 has_compliant_args = true;
1375 #region IMethodData Members
1377 public MemberName MethodName {
1383 public Type ReturnType {
1389 public EmitContext CreateEmitContext (ILGenerator ig)
1391 throw new NotImplementedException ();
1394 public bool IsExcluded()
1399 GenericMethod IMethodData.GenericMethod {
1405 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1412 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1414 public interface IMethodData
1416 CallingConventions CallingConventions { get; }
1417 Location Location { get; }
1418 MemberName MethodName { get; }
1419 Type ReturnType { get; }
1420 GenericMethod GenericMethod { get; }
1421 ParametersCompiled ParameterInfo { get; }
1423 Attributes OptAttributes { get; }
1424 ToplevelBlock Block { get; set; }
1426 EmitContext CreateEmitContext (ILGenerator ig);
1427 ObsoleteAttribute GetObsoleteAttribute ();
1428 string GetSignatureForError ();
1430 bool IsClsComplianceRequired ();
1432 void EmitExtraSymbolInfo (SourceMethod source);
1436 // Encapsulates most of the Method's state
1438 public class MethodData {
1439 static FieldInfo methodbuilder_attrs_field;
1440 public readonly IMethodData method;
1442 public readonly GenericMethod GenericMethod;
1445 // Are we implementing an interface ?
1447 public MethodInfo implementing;
1452 protected InterfaceMemberBase member;
1453 protected Modifiers modifiers;
1454 protected MethodAttributes flags;
1455 protected Type declaring_type;
1456 protected MethodInfo parent_method;
1458 MethodBuilder builder = null;
1459 public MethodBuilder MethodBuilder {
1465 public Type DeclaringType {
1467 return declaring_type;
1471 public MethodData (InterfaceMemberBase member,
1472 Modifiers modifiers, MethodAttributes flags, IMethodData method)
1474 this.member = member;
1475 this.modifiers = modifiers;
1478 this.method = method;
1481 public MethodData (InterfaceMemberBase member,
1482 Modifiers modifiers, MethodAttributes flags,
1483 IMethodData method, MethodBuilder builder,
1484 GenericMethod generic, MethodInfo parent_method)
1485 : this (member, modifiers, flags, method)
1487 this.builder = builder;
1488 this.GenericMethod = generic;
1489 this.parent_method = parent_method;
1492 public bool Define (DeclSpace parent, string method_full_name, Report Report)
1494 string name = method.MethodName.Basename;
1496 TypeContainer container = parent.PartialContainer;
1498 PendingImplementation pending = container.PendingImplementations;
1499 if (pending != null){
1500 implementing = pending.IsInterfaceMethod (name, member.InterfaceType, this);
1502 if (member.InterfaceType != null){
1503 if (implementing == null){
1504 if (member is PropertyBase) {
1505 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
1506 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1507 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1510 Report.Error (539, method.Location,
1511 "`{0}.{1}' in explicit interface declaration is not a member of interface",
1512 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1516 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
1517 Report.SymbolRelatedToPreviousError (implementing);
1518 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1519 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1523 if (implementing != null) {
1524 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
1525 if (prop_method == null) {
1526 if (TypeManager.IsSpecialMethod (implementing)) {
1527 Report.SymbolRelatedToPreviousError (implementing);
1528 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
1529 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
1530 implementing.Name.StartsWith ("get_") ? "get" : "set");
1532 } else if (implementing.DeclaringType.IsInterface) {
1533 if (!implementing.IsSpecialName) {
1534 Report.SymbolRelatedToPreviousError (implementing);
1535 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1536 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1539 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
1540 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1541 Report.SymbolRelatedToPreviousError (implementing);
1542 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1543 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
1552 // For implicit implementations, make sure we are public, for
1553 // explicit implementations, make sure we are private.
1555 if (implementing != null){
1557 // Setting null inside this block will trigger a more
1558 // verbose error reporting for missing interface implementations
1560 // The "candidate" function has been flagged already
1561 // but it wont get cleared
1563 if (member.IsExplicitImpl){
1564 if (method.ParameterInfo.HasParams && !TypeManager.GetParameterData (implementing).HasParams) {
1565 Report.SymbolRelatedToPreviousError (implementing);
1566 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1567 method.GetSignatureForError ());
1571 if (implementing.DeclaringType.IsInterface) {
1573 // If this is an interface method implementation,
1574 // check for public accessibility
1576 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
1578 implementing = null;
1580 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
1581 // We may never be private.
1582 implementing = null;
1584 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
1586 // We may be protected if we're overriding something.
1588 implementing = null;
1593 // Static is not allowed
1595 if ((modifiers & Modifiers.STATIC) != 0){
1596 implementing = null;
1601 // If implementing is still valid, set flags
1603 if (implementing != null){
1605 // When implementing interface methods, set NewSlot
1606 // unless, we are overwriting a method.
1608 if (implementing.DeclaringType.IsInterface){
1609 if ((modifiers & Modifiers.OVERRIDE) == 0)
1610 flags |= MethodAttributes.NewSlot;
1613 MethodAttributes.Virtual |
1614 MethodAttributes.HideBySig;
1616 // Set Final unless we're virtual, abstract or already overriding a method.
1617 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
1618 flags |= MethodAttributes.Final;
1621 DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
1623 if (builder == null)
1626 if (container.CurrentType != null)
1627 declaring_type = container.CurrentType;
1629 declaring_type = container.TypeBuilder;
1631 if (implementing != null && member.IsExplicitImpl) {
1632 container.TypeBuilder.DefineMethodOverride (builder, implementing);
1635 TypeManager.AddMethod (builder, method);
1637 if (GenericMethod != null) {
1638 bool is_override = member.IsExplicitImpl |
1639 ((modifiers & Modifiers.OVERRIDE) != 0);
1641 if (implementing != null)
1642 parent_method = implementing;
1644 if (!GenericMethod.DefineType (GenericMethod, builder, parent_method, is_override))
1653 /// Create the MethodBuilder for the method
1655 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
1657 if (builder == null) {
1658 builder = container.TypeBuilder.DefineMethod (
1659 method_name, flags, method.CallingConventions,
1661 param.GetEmitTypes ());
1666 // Generic method has been already defined to resolve method parameters
1667 // correctly when they use type parameters
1669 builder.SetParameters (param.GetEmitTypes ());
1670 builder.SetReturnType (method.ReturnType);
1671 if (builder.Attributes != flags) {
1673 if (methodbuilder_attrs_field == null)
1674 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
1675 methodbuilder_attrs_field.SetValue (builder, flags);
1677 container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
1685 public void Emit (DeclSpace parent)
1687 method.ParameterInfo.ApplyAttributes (MethodBuilder);
1689 if (GenericMethod != null)
1690 GenericMethod.EmitAttributes ();
1693 // clear the pending implementation flag
1695 if (implementing != null)
1696 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName.Basename,
1697 member.InterfaceType, this, member.IsExplicitImpl);
1699 SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
1701 ToplevelBlock block = method.Block;
1702 if (block != null) {
1703 BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType);
1704 if (block.Resolve (null, bc, method.ParameterInfo, method)) {
1705 EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
1706 if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1707 ec.ReturnLabel = bc.ReturnLabel;
1708 ec.HasReturnLabel = true;
1715 if (source != null) {
1716 method.EmitExtraSymbolInfo (source);
1717 source.CloseMethod ();
1722 public class Destructor : MethodOrOperator
1724 const Modifiers AllowedModifiers =
1728 static readonly string[] attribute_targets = new string [] { "method" };
1730 public static readonly string MetadataName = "Finalize";
1732 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
1733 : base (parent, null, TypeManager.system_void_expr, mod, AllowedModifiers,
1734 new MemberName (MetadataName, l), attrs, parameters)
1736 ModFlags &= ~Modifiers.PRIVATE;
1737 ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
1740 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1742 if (a.Type == pa.Conditional) {
1743 Error_ConditionalAttributeIsNotValid ();
1747 base.ApplyAttributeBuilder (a, cb, pa);
1750 protected override bool CheckBase ()
1752 if (!base.CheckBase ())
1755 if (Parent.PartialContainer.BaseCache == null)
1758 Type base_type = Parent.PartialContainer.BaseCache.Container.Type;
1759 if (base_type != null && Block != null) {
1760 MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.TypeBuilder, base_type, MetadataName, Location);
1761 if (method_expr == null)
1762 throw new NotImplementedException ();
1764 method_expr.IsBase = true;
1765 method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location);
1767 ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation);
1768 new_block.EndLocation = Block.EndLocation;
1770 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
1771 Block try_block = new Block (new_block, block);
1774 // 0-size arguments to avoid CS0250 error
1775 // TODO: Should use AddScopeStatement or something else which emits correct
1778 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
1779 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
1787 public override string GetSignatureForError ()
1789 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
1792 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
1797 public override string[] ValidAttributeTargets {
1799 return attribute_targets;
1804 // Ooouh Martin, templates are missing here.
1805 // When it will be possible move here a lot of child code and template method type.
1806 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
1807 protected MethodData method_data;
1808 protected ToplevelBlock block;
1809 protected Dictionary<SecurityAction, PermissionSet> declarative_security;
1811 // The accessor are created even if they are not wanted.
1812 // But we need them because their names are reserved.
1813 // Field says whether accessor will be emited or not
1814 public readonly bool IsDummy;
1816 protected readonly string prefix;
1818 ReturnParameter return_attributes;
1820 public AbstractPropertyEventMethod (PropertyBasedMember member, string prefix)
1821 : base (member.Parent, SetupName (prefix, member, member.Location), null)
1823 this.prefix = prefix;
1827 public AbstractPropertyEventMethod (InterfaceMemberBase member, Accessor accessor,
1829 : base (member.Parent, SetupName (prefix, member, accessor.Location),
1830 accessor.Attributes)
1832 this.prefix = prefix;
1833 this.block = accessor.Block;
1836 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
1838 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
1841 public void UpdateName (InterfaceMemberBase member)
1843 SetMemberName (SetupName (prefix, member, Location));
1846 #region IMethodData Members
1848 public ToplevelBlock Block {
1858 public CallingConventions CallingConventions {
1860 return CallingConventions.Standard;
1864 public EmitContext CreateEmitContext (ILGenerator ig)
1866 return new EmitContext (this, ig, ReturnType);
1869 public bool IsExcluded ()
1874 GenericMethod IMethodData.GenericMethod {
1880 public MemberName MethodName {
1886 public Type[] ParameterTypes {
1888 return ParameterInfo.Types;
1892 public abstract ParametersCompiled ParameterInfo { get ; }
1893 public abstract Type ReturnType { get; }
1897 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1899 if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
1900 Report.Error (1667, a.Location,
1901 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
1902 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
1906 if (a.IsValidSecurityAttribute ()) {
1907 if (declarative_security == null)
1908 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1909 a.ExtractSecurityPermissionSet (declarative_security);
1913 if (a.Target == AttributeTargets.Method) {
1914 method_data.MethodBuilder.SetCustomAttribute (cb);
1918 if (a.Target == AttributeTargets.ReturnValue) {
1919 if (return_attributes == null)
1920 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
1922 return_attributes.ApplyAttributeBuilder (a, cb, pa);
1926 ApplyToExtraTarget (a, cb, pa);
1929 protected virtual void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1931 throw new NotSupportedException ("You forgot to define special attribute target handling");
1934 // It is not supported for the accessors
1935 public sealed override bool Define()
1937 throw new NotSupportedException ();
1940 public virtual void Emit (DeclSpace parent)
1942 method_data.Emit (parent);
1944 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
1945 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
1946 if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
1947 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
1949 if (TypeManager.IsDynamicType (ReturnType)) {
1950 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
1951 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
1953 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
1954 if (trans_flags != null) {
1955 var pa = PredefinedAttributes.Get.DynamicTransform;
1956 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
1957 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
1958 return_attributes.Builder.SetCustomAttribute (
1959 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
1964 if (OptAttributes != null)
1965 OptAttributes.Emit ();
1967 if (declarative_security != null) {
1968 foreach (var de in declarative_security) {
1969 method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1976 public override bool EnableOverloadChecks (MemberCore overload)
1978 // This can only happen with indexers and it will
1979 // be catched as indexer difference
1980 if (overload is AbstractPropertyEventMethod)
1983 if (overload is MethodCore) {
1984 caching_flags |= Flags.MethodOverloadsExist;
1990 public override bool IsClsComplianceRequired()
1995 public bool IsDuplicateImplementation (MethodCore method)
1997 if (!MemberName.Equals (method.MemberName))
2000 Type[] param_types = method.ParameterTypes;
2002 if (param_types == null || param_types.Length != ParameterTypes.Length)
2005 for (int i = 0; i < param_types.Length; i++)
2006 if (param_types [i] != ParameterTypes [i])
2009 Report.SymbolRelatedToPreviousError (method);
2010 Report.Error (82, Location, "A member `{0}' is already reserved",
2011 method.GetSignatureForError ());
2015 public override bool IsUsed
2026 // Represents header string for documentation comment.
2028 public override string DocCommentHeader {
2029 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2032 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2036 public class Operator : MethodOrOperator {
2038 const Modifiers AllowedModifiers =
2044 public enum OpType : byte {
2054 // Unary and Binary operators
2077 // Implicit and Explicit
2081 // Just because of enum
2085 public readonly OpType OperatorType;
2087 static readonly string [] [] names;
2091 names = new string[(int)OpType.TOP][];
2092 names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2093 names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2094 names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2095 names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2096 names [(int) OpType.True] = new string [] { "true", "op_True" };
2097 names [(int) OpType.False] = new string [] { "false", "op_False" };
2098 names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2099 names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2100 names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2101 names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2102 names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2103 names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2104 names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2105 names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2106 names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2107 names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2108 names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2109 names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2110 names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2111 names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2112 names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2113 names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2114 names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2115 names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2116 names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2117 names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2120 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
2121 Modifiers mod_flags, ParametersCompiled parameters,
2122 ToplevelBlock block, Attributes attrs, Location loc)
2123 : base (parent, null, ret_type, mod_flags, AllowedModifiers,
2124 new MemberName (GetMetadataName (type), loc), attrs, parameters)
2126 OperatorType = type;
2130 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2132 if (a.Type == pa.Conditional) {
2133 Error_ConditionalAttributeIsNotValid ();
2137 base.ApplyAttributeBuilder (a, cb, pa);
2140 public override bool Define ()
2142 const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2143 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2144 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2147 if (!base.Define ())
2150 // imlicit and explicit operator of same types are not allowed
2151 if (OperatorType == OpType.Explicit)
2152 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), Parameters, Report);
2153 else if (OperatorType == OpType.Implicit)
2154 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), Parameters, Report);
2156 Type declaring_type = MethodData.DeclaringType;
2157 Type return_type = MemberType;
2158 Type first_arg_type = ParameterTypes [0];
2160 Type first_arg_type_unwrap = first_arg_type;
2161 if (TypeManager.IsNullableType (first_arg_type))
2162 first_arg_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (first_arg_type) [0]);
2164 Type return_type_unwrap = return_type;
2165 if (TypeManager.IsNullableType (return_type))
2166 return_type_unwrap = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (return_type) [0]);
2168 if (TypeManager.IsDynamicType (return_type) || TypeManager.IsDynamicType (first_arg_type)) {
2169 Report.Error (1964, Location,
2170 "User-defined operator `{0}' cannot convert to or from the dynamic type",
2171 GetSignatureForError ());
2177 // Rules for conversion operators
2179 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2180 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
2181 Report.Error (555, Location,
2182 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2187 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
2188 conv_type = first_arg_type;
2189 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
2190 conv_type = return_type;
2192 Report.Error (556, Location,
2193 "User-defined conversion must convert to or from the enclosing type");
2198 // Because IsInterface and IsClass are not supported
2200 if (!TypeManager.IsGenericParameter (conv_type)) {
2201 if (conv_type.IsInterface) {
2202 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2203 GetSignatureForError ());
2207 if (conv_type.IsClass) {
2208 if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
2209 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2210 GetSignatureForError ());
2214 if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
2215 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2216 GetSignatureForError ());
2221 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2222 if (first_arg_type != declaring_type || Parameters.Types [1] != TypeManager.int32_type) {
2223 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");
2226 } else if (Parameters.Count == 1) {
2227 // Checks for Unary operators
2229 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2230 if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
2231 Report.Error (448, Location,
2232 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2235 if (first_arg_type != declaring_type) {
2237 559, Location, "The parameter type for ++ or -- operator must be the containing type");
2242 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)){
2243 Report.Error (562, Location,
2244 "The parameter type of a unary operator must be the containing type");
2248 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2249 if (return_type != TypeManager.bool_type){
2252 "The return type of operator True or False " +
2258 } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
2259 // Checks for Binary operators
2261 var second_arg_type = ParameterTypes [1];
2262 if (TypeManager.IsNullableType (second_arg_type))
2263 second_arg_type = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (second_arg_type) [0]);
2265 if (!TypeManager.IsEqual (second_arg_type, declaring_type)) {
2266 Report.Error (563, Location,
2267 "One of the parameters of a binary operator must be the containing type");
2275 protected override bool ResolveMemberType ()
2277 if (!base.ResolveMemberType ())
2280 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2284 // Operator cannot be override
2285 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
2290 public static string GetName (OpType ot)
2292 return names [(int) ot] [0];
2295 public static string GetName (string metadata_name)
2297 for (int i = 0; i < names.Length; ++i) {
2298 if (names [i] [1] == metadata_name)
2299 return names [i] [0];
2304 public static string GetMetadataName (OpType ot)
2306 return names [(int) ot] [1];
2309 public static string GetMetadataName (string name)
2311 for (int i = 0; i < names.Length; ++i) {
2312 if (names [i] [0] == name)
2313 return names [i] [1];
2318 public OpType GetMatchingOperator ()
2320 switch (OperatorType) {
2321 case OpType.Equality:
2322 return OpType.Inequality;
2323 case OpType.Inequality:
2324 return OpType.Equality;
2326 return OpType.False;
2329 case OpType.GreaterThan:
2330 return OpType.LessThan;
2331 case OpType.LessThan:
2332 return OpType.GreaterThan;
2333 case OpType.GreaterThanOrEqual:
2334 return OpType.LessThanOrEqual;
2335 case OpType.LessThanOrEqual:
2336 return OpType.GreaterThanOrEqual;
2342 public override string GetSignatureForError ()
2344 StringBuilder sb = new StringBuilder ();
2345 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2346 sb.AppendFormat ("{0}.{1} operator {2}",
2347 Parent.GetSignatureForError (), GetName (OperatorType), type_name.GetSignatureForError ());
2350 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2353 sb.Append (Parameters.GetSignatureForError ());
2354 return sb.ToString ();
2359 // This is used to compare method signatures
2361 struct MethodSignature {
2363 public Type RetType;
2364 public Type [] Parameters;
2367 /// This delegate is used to extract methods which have the
2368 /// same signature as the argument
2370 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
2372 public MethodSignature (string name, Type ret_type, Type [] parameters)
2377 if (parameters == null)
2378 Parameters = Type.EmptyTypes;
2380 Parameters = parameters;
2383 public override string ToString ()
2386 if (Parameters.Length != 0){
2387 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
2388 for (int i = 0; i < Parameters.Length; i++){
2389 sb.Append (Parameters [i]);
2390 if (i+1 < Parameters.Length)
2393 pars = sb.ToString ();
2396 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
2399 public override int GetHashCode ()
2401 return Name.GetHashCode ();
2404 public override bool Equals (Object o)
2406 MethodSignature other = (MethodSignature) o;
2408 if (other.Name != Name)
2411 if (other.RetType != RetType)
2414 if (Parameters == null){
2415 if (other.Parameters == null)
2420 if (other.Parameters == null)
2423 int c = Parameters.Length;
2424 if (other.Parameters.Length != c)
2427 for (int i = 0; i < c; i++)
2428 if (other.Parameters [i] != Parameters [i])
2434 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
2436 MethodSignature sig = (MethodSignature) filter_criteria;
2438 if (m.Name != sig.Name)
2442 MethodInfo mi = m as MethodInfo;
2443 PropertyInfo pi = m as PropertyInfo;
2446 ReturnType = mi.ReturnType;
2447 else if (pi != null)
2448 ReturnType = pi.PropertyType;
2453 // we use sig.RetType == null to mean `do not check the
2454 // method return value.
2456 if (sig.RetType != null) {
2457 if (!TypeManager.IsEqual (ReturnType, sig.RetType))
2463 args = TypeManager.GetParameterData (mi).Types;
2465 args = TypeManager.GetParameterData (pi).Types;
2466 Type [] sigp = sig.Parameters;
2468 if (args.Length != sigp.Length)
2471 for (int i = args.Length - 1; i >= 0; i--)
2472 if (!TypeManager.IsEqual (args [i], sigp [i]))