1 //
2 // method.cs: Method based declarations
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Martin Baulig (martin@ximian.com)
6 //          Marek Safar (marek.safar@gmail.com)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
12 // Copyright 2011 Xamarin Inc.
13 //
14 
15 using System;
16 using System.Collections.Generic;
17 using System.Security;
18 using System.Security.Permissions;
19 using System.Text;
20 using System.Linq;
21 using Mono.CompilerServices.SymbolWriter;
22 using System.Runtime.CompilerServices;
23 
24 #if MOBILE
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
29 
30 #if STATIC
31 using MetaType = IKVM.Reflection.Type;
32 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
33 using IKVM.Reflection;
34 using IKVM.Reflection.Emit;
35 #else
36 using MetaType = System.Type;
37 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
38 using System.Reflection;
39 using System.Reflection.Emit;
40 #endif
41 
42 namespace Mono.CSharp {
43 
44 	public abstract class MethodCore : InterfaceMemberBase, IParametersMember
45 	{
46 		protected ParametersCompiled parameters;
47 		protected ToplevelBlock block;
48 		protected MethodSpec spec;
49 
MethodCore(TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs, ParametersCompiled parameters)50 		protected MethodCore (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
51 			MemberName name, Attributes attrs, ParametersCompiled parameters)
52 			: base (parent, type, mod, allowed_mod, name, attrs)
53 		{
54 			this.parameters = parameters;
55 		}
56 
57 		public override Variance ExpectedMemberTypeVariance {
58 			get {
59 				return Variance.Covariant;
60 			}
61 		}
62 
63 		//
64 		//  Returns the System.Type array for the parameters of this method
65 		//
66 		public TypeSpec [] ParameterTypes {
67 			get {
68 				return parameters.Types;
69 			}
70 		}
71 
72 		public ParametersCompiled ParameterInfo {
73 			get {
74 				return parameters;
75 			}
76 		}
77 
78 		AParametersCollection IParametersMember.Parameters {
79 			get { return parameters; }
80 		}
81 
82 		public ToplevelBlock Block {
83 			get {
84 				return block;
85 			}
86 
87 			set {
88 				block = value;
89 			}
90 		}
91 
92 		public CallingConventions CallingConventions {
93 			get {
94 				CallingConventions cc = parameters.CallingConvention;
95 				if (!IsInterface)
96 					if ((ModFlags & Modifiers.STATIC) == 0)
97 						cc |= CallingConventions.HasThis;
98 
99 				// FIXME: How is `ExplicitThis' used in C#?
100 
101 				return cc;
102 			}
103 		}
104 
CheckOverrideAgainstBase(MemberSpec base_member)105 		protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
106 		{
107 			bool res = base.CheckOverrideAgainstBase (base_member);
108 
109 			//
110 			// Check that the permissions are not being changed
111 			//
112 			if (!CheckAccessModifiers (this, base_member)) {
113 				Error_CannotChangeAccessModifiers (this, base_member);
114 				res = false;
115 			}
116 
117 			return res;
118 		}
119 
CheckBase()120 		protected override bool CheckBase ()
121 		{
122 			// Check whether arguments were correct.
123 			if (!DefineParameters (parameters))
124 				return false;
125 
126 			return base.CheckBase ();
127 		}
128 
129 		//
130 		//   Represents header string for documentation comment.
131 		//
132 		public override string DocCommentHeader
133 		{
134 			get { return "M:"; }
135 		}
136 
Emit()137 		public override void Emit ()
138 		{
139 			if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
140 				parameters.CheckConstraints (this);
141 			}
142 
143 			base.Emit ();
144 		}
145 
EnableOverloadChecks(MemberCore overload)146 		public override bool EnableOverloadChecks (MemberCore overload)
147 		{
148 			if (overload is MethodCore) {
149 				caching_flags |= Flags.MethodOverloadsExist;
150 				return true;
151 			}
152 
153 			if (overload is AbstractPropertyEventMethod)
154 				return true;
155 
156 			return base.EnableOverloadChecks (overload);
157 		}
158 
GetSignatureForDocumentation()159 		public override string GetSignatureForDocumentation ()
160 		{
161 			string s = base.GetSignatureForDocumentation ();
162 			if (MemberName.Arity > 0)
163 				s += "``" + MemberName.Arity.ToString ();
164 
165 			return s + parameters.GetSignatureForDocumentation ();
166 		}
167 
PrepareEmit()168 		public override void PrepareEmit ()
169 		{
170 			base.PrepareEmit ();
171 			parameters.ResolveDefaultValues (this);
172 		}
173 
174 		public MethodSpec Spec {
175 			get { return spec; }
176 		}
177 
VerifyClsCompliance()178 		protected override bool VerifyClsCompliance ()
179 		{
180 			if (!base.VerifyClsCompliance ())
181 				return false;
182 
183 			if (parameters.HasArglist) {
184 				Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
185 			}
186 
187 			if (member_type != null && !member_type.IsCLSCompliant ()) {
188 				Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
189 					GetSignatureForError ());
190 			}
191 
192 			parameters.VerifyClsCompliance (this);
193 			return true;
194 		}
195 	}
196 
197 	public interface IGenericMethodDefinition : IMethodDefinition
198 	{
199 		TypeParameterSpec[] TypeParameters { get; }
200 		int TypeParametersCount { get; }
201 
202 //		MethodInfo MakeGenericMethod (TypeSpec[] targs);
203 	}
204 
205 	public sealed class MethodSpec : MemberSpec, IParametersMember
206 	{
207 		MethodBase inflatedMetaInfo;
208 		AParametersCollection parameters;
209 		TypeSpec returnType;
210 
211 		TypeSpec[] targs;
212 		TypeParameterSpec[] constraints;
213 
214 		public static readonly MethodSpec Excluded = new MethodSpec (MemberKind.Method, InternalType.FakeInternalType, null, null, ParametersCompiled.EmptyReadOnlyParameters, 0);
215 
MethodSpec(MemberKind kind, TypeSpec declaringType, IMethodDefinition details, TypeSpec returnType, AParametersCollection parameters, Modifiers modifiers)216 		public MethodSpec (MemberKind kind, TypeSpec declaringType, IMethodDefinition details, TypeSpec returnType,
217 			AParametersCollection parameters, Modifiers modifiers)
218 			: base (kind, declaringType, details, modifiers)
219 		{
220 			this.parameters = parameters;
221 			this.returnType = returnType;
222 		}
223 
224 		#region Properties
225 
226 		public override int Arity {
227 			get {
228 				return IsGeneric ? GenericDefinition.TypeParametersCount : 0;
229 			}
230 		}
231 
232 		public TypeParameterSpec[] Constraints {
233 			get {
234 				if (constraints == null && IsGeneric)
235 					constraints = GenericDefinition.TypeParameters;
236 
237 				return constraints;
238 			}
239 		}
240 
241 		public bool IsConstructor {
242 			get {
243 				return Kind == MemberKind.Constructor;
244 			}
245 		}
246 
247 		public new IMethodDefinition MemberDefinition {
248 			get {
249 				return (IMethodDefinition) definition;
250 			}
251 		}
252 
253 		public IGenericMethodDefinition GenericDefinition {
254 			get {
255 				return (IGenericMethodDefinition) definition;
256 			}
257 		}
258 
259 		public bool IsAsync {
260 			get {
261 				return (Modifiers & Modifiers.ASYNC) != 0;
262 			}
263 		}
264 
265 		public bool IsExtensionMethod {
266 			get {
267 				return IsStatic && parameters.HasExtensionMethodType;
268 			}
269 		}
270 
271 		public bool IsSealed {
272 			get {
273 				return (Modifiers & Modifiers.SEALED) != 0;
274 			}
275 		}
276 
277 		// When is virtual or abstract
278 		public bool IsVirtual {
279 			get {
280 				return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
281 			}
282 		}
283 
284 		public bool IsReservedMethod {
285 			get {
286 				return Kind == MemberKind.Operator || IsAccessor;
287 			}
288 		}
289 
290 		TypeSpec IInterfaceMemberSpec.MemberType {
291 			get {
292 				return returnType;
293 			}
294 		}
295 
296 		public AParametersCollection Parameters {
297 			get {
298 				return parameters;
299 			}
300 		}
301 
302 		public TypeSpec ReturnType {
303 			get {
304 				return returnType;
305 			}
306 		}
307 
308 		public TypeSpec[] TypeArguments {
309 			get {
310 				return targs;
311 			}
312 		}
313 
314 		#endregion
315 
GetGenericMethodDefinition()316 		public MethodSpec GetGenericMethodDefinition ()
317 		{
318 			if (!IsGeneric && !DeclaringType.IsGeneric)
319 				return this;
320 
321 			return MemberCache.GetMember (declaringType, this);
322 		}
323 
GetMetaInfo()324 		public MethodBase GetMetaInfo ()
325 		{
326 			//
327 			// inflatedMetaInfo is extra field needed for cases where we
328 			// inflate method but another nested type can later inflate
329 			// again (the cache would be build with inflated metaInfo) and
330 			// TypeBuilder can work with method definitions only
331 			//
332 			if (inflatedMetaInfo == null) {
333 				if ((state & StateFlags.PendingMetaInflate) != 0) {
334 					var dt_meta = DeclaringType.GetMetaInfo ();
335 
336 					if (DeclaringType.IsTypeBuilder) {
337 						if (IsConstructor)
338 							inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) MemberDefinition.Metadata);
339 						else
340 							inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) MemberDefinition.Metadata);
341 					} else {
342 #if STATIC
343 						// it should not be reached
344 						throw new NotImplementedException ();
345 #else
346 						inflatedMetaInfo = MethodInfo.GetMethodFromHandle (MemberDefinition.Metadata.MethodHandle, dt_meta.TypeHandle);
347 #endif
348 					}
349 
350 					state &= ~StateFlags.PendingMetaInflate;
351 				} else {
352 					inflatedMetaInfo = MemberDefinition.Metadata;
353 				}
354 			}
355 
356 			if ((state & StateFlags.PendingMakeMethod) != 0) {
357 				var sre_targs = new MetaType[targs.Length];
358 				for (int i = 0; i < sre_targs.Length; ++i)
359 					sre_targs[i] = targs[i].GetMetaInfo ();
360 
361 				inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs);
362 				state &= ~StateFlags.PendingMakeMethod;
363 			}
364 
365 			return inflatedMetaInfo;
366 		}
367 
GetSignatureForDocumentation()368 		public override string GetSignatureForDocumentation ()
369 		{
370 			string name;
371 			switch (Kind) {
372 			case MemberKind.Constructor:
373 				name = "#ctor";
374 				break;
375 			case MemberKind.Method:
376 				if (Arity > 0)
377 					name = Name + "``" + Arity.ToString ();
378 				else
379 					name = Name;
380 
381 				break;
382 			default:
383 				name = Name;
384 				break;
385 			}
386 
387 			name = DeclaringType.GetSignatureForDocumentation () + "." + name + parameters.GetSignatureForDocumentation ();
388 			if (Kind == MemberKind.Operator) {
389 				var op = Operator.GetType (Name).Value;
390 				if (op == Operator.OpType.Explicit || op == Operator.OpType.Implicit) {
391 					name += "~" + ReturnType.GetSignatureForDocumentation ();
392 				}
393 			}
394 
395 			return name;
396 		}
397 
GetSignatureForError()398 		public override string GetSignatureForError ()
399 		{
400 			string name;
401 			if (IsConstructor) {
402 				name = DeclaringType.GetSignatureForError () + "." + DeclaringType.Name;
403 			} else if (Kind == MemberKind.Operator) {
404 				var op = Operator.GetType (Name).Value;
405 				if (op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) {
406 					name = DeclaringType.GetSignatureForError () + "." + Operator.GetName (op) + " operator " + returnType.GetSignatureForError ();
407 				} else {
408 					name = DeclaringType.GetSignatureForError () + ".operator " + Operator.GetName (op);
409 				}
410 			} else if (IsAccessor) {
411 				int split = Name.IndexOf ('_');
412 				name = Name.Substring (split + 1);
413 				var postfix = Name.Substring (0, split);
414 				if (split == 3) {
415 					var pc = parameters.Count;
416 					if (pc > 0 && postfix == "get") {
417 						name = "this" + parameters.GetSignatureForError ("[", "]", pc);
418 					} else if (pc > 1 && postfix == "set") {
419 						name = "this" + parameters.GetSignatureForError ("[", "]", pc - 1);
420 					}
421 				}
422 
423 				return DeclaringType.GetSignatureForError () + "." + name + "." + postfix;
424 			} else {
425 				name = base.GetSignatureForError ();
426 				if (targs != null)
427 					name += "<" + TypeManager.CSharpName (targs) + ">";
428 				else if (IsGeneric)
429 					name += "<" + TypeManager.CSharpName (GenericDefinition.TypeParameters) + ">";
430 			}
431 
432 			return name + parameters.GetSignatureForError ();
433 		}
434 
InflateMember(TypeParameterInflator inflator)435 		public override MemberSpec InflateMember (TypeParameterInflator inflator)
436 		{
437 			var ms = (MethodSpec) base.InflateMember (inflator);
438 			ms.inflatedMetaInfo = null;
439 			ms.returnType = inflator.Inflate (returnType);
440 			ms.parameters = parameters.Inflate (inflator);
441 			if (IsGeneric)
442 				ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints);
443 
444 			return ms;
445 		}
446 
447 #if DEBUG
448 		int counter = 100000;
449 #endif
450 
MakeGenericMethod(IMemberContext context, params TypeSpec[] targs)451 		public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs)
452 		{
453 			if (targs == null)
454 				throw new ArgumentNullException ();
455 // TODO MemberCache
456 //			if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance))
457 //				return ginstance;
458 
459 			//if (generic_intances == null)
460 			//    generic_intances = new Dictionary<TypeSpec[], Method> (TypeSpecArrayComparer.Default);
461 
462 			var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs);
463 
464 			var inflated = (MethodSpec) MemberwiseClone ();
465 			inflated.declaringType = inflator.TypeInstance;
466 			inflated.returnType = inflator.Inflate (returnType);
467 			inflated.parameters = parameters.Inflate (inflator);
468 			inflated.targs = targs;
469 			inflated.constraints = TypeParameterSpec.InflateConstraints (inflator, constraints ?? GenericDefinition.TypeParameters);
470 			inflated.state |= StateFlags.PendingMakeMethod;
471 
472 #if DEBUG
473 			inflated.ID += counter;
474 			counter += 100000;
475 #endif
476 			//			if (inflated.parent == null)
477 			//				inflated.parent = parent;
478 
479 			//generic_intances.Add (targs, inflated);
480 			return inflated;
481 		}
482 
Mutate(TypeParameterMutator mutator)483 		public MethodSpec Mutate (TypeParameterMutator mutator)
484 		{
485 			var targs = TypeArguments;
486 			if (targs != null)
487 				targs = mutator.Mutate (targs);
488 
489 			var decl = DeclaringType;
490 			if (DeclaringType.IsGenericOrParentIsGeneric) {
491 				decl = mutator.Mutate (decl);
492 			}
493 
494 			if (targs == TypeArguments && decl == DeclaringType)
495 				return this;
496 
497 			var ms = (MethodSpec) MemberwiseClone ();
498 			if (decl != DeclaringType) {
499 				ms.inflatedMetaInfo = null;
500 				ms.declaringType = decl;
501 				ms.state |= StateFlags.PendingMetaInflate;
502 			}
503 
504 			if (targs != null) {
505 				ms.targs = targs;
506 				ms.state |= StateFlags.PendingMakeMethod;
507 			}
508 
509 			return ms;
510 		}
511 
ResolveMissingDependencies(MemberSpec caller)512 		public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
513 		{
514 			var missing = returnType.ResolveMissingDependencies (this);
515 			foreach (var pt in parameters.Types) {
516 				var m = pt.GetMissingDependencies (this);
517 				if (m == null)
518 					continue;
519 
520 				if (missing == null)
521 					missing = new List<MissingTypeSpecReference> ();
522 
523 				missing.AddRange (m);
524 			}
525 
526 			if (Arity > 0) {
527 				foreach (var tp in GenericDefinition.TypeParameters) {
528 					var m = tp.GetMissingDependencies (this);
529 
530 					if (m == null)
531 						continue;
532 
533 					if (missing == null)
534 						missing = new List<MissingTypeSpecReference> ();
535 
536 					missing.AddRange (m);
537 				}
538 			}
539 
540 			return missing;
541 		}
542 	}
543 
544 	public abstract class MethodOrOperator : MethodCore, IMethodData, IMethodDefinition
545 	{
546 		ReturnParameter return_attributes;
547 		SecurityType declarative_security;
548 		protected MethodData MethodData;
549 
550 		static readonly string[] attribute_targets = new string [] { "method", "return" };
551 
MethodOrOperator(TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs, ParametersCompiled parameters)552 		protected MethodOrOperator (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name,
553 				Attributes attrs, ParametersCompiled parameters)
554 			: base (parent, type, mod, allowed_mod, name, attrs, parameters)
555 		{
556 		}
557 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)558 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
559 		{
560 			if (a.Target == AttributeTargets.ReturnValue) {
561 				CreateReturnBuilder ().ApplyAttributeBuilder (a, ctor, cdata, pa);
562 				return;
563 			}
564 
565 			if (a.Type == pa.MethodImpl) {
566 				if ((ModFlags & Modifiers.ASYNC) != 0 && (a.GetMethodImplOptions () & MethodImplOptions.Synchronized) != 0) {
567 					Report.Error (4015, a.Location, "`{0}': Async methods cannot use `MethodImplOptions.Synchronized'",
568 						GetSignatureForError ());
569 				}
570 
571 				is_external_implementation = a.IsInternalCall ();
572 			} else if (a.Type == pa.DllImport) {
573 				const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
574 				if ((ModFlags & extern_static) != extern_static) {
575 					Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
576 				}
577 
578 				if (MemberName.IsGeneric || Parent.IsGenericOrParentIsGeneric) {
579 					Report.Error (7042, a.Location,
580 						"The DllImport attribute cannot be applied to a method that is generic or contained in a generic type");
581 				}
582 
583 				is_external_implementation = true;
584 			}
585 
586 			if (a.IsValidSecurityAttribute ()) {
587 				a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
588 				return;
589 			}
590 
591 			if (MethodBuilder != null)
592 				MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
593 		}
594 
595 		public override AttributeTargets AttributeTargets {
596 			get {
597 				return AttributeTargets.Method;
598 			}
599 		}
600 
601 		MethodBase IMethodDefinition.Metadata {
602 			get {
603 				return MethodData.MethodBuilder;
604 			}
605 		}
606 
607 		// TODO: Remove and use MethodData abstraction
608 		public MethodBuilder MethodBuilder {
609 			get {
610 				return MethodData.MethodBuilder;
611 			}
612 		}
613 
CheckForDuplications()614 		protected override bool CheckForDuplications ()
615 		{
616 			return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
617 		}
618 
CreateEmitContext(ILGenerator ig, SourceMethodBuilder sourceMethod)619 		public virtual EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
620 		{
621 			return new EmitContext (this, ig, MemberType, sourceMethod);
622 		}
623 
CreateReturnBuilder()624 		ReturnParameter CreateReturnBuilder ()
625 		{
626 			return return_attributes ?? (return_attributes = new ReturnParameter (this, MethodBuilder, Location));
627 		}
628 
Define()629 		public override bool Define ()
630 		{
631 			if (!base.Define ())
632 				return false;
633 
634 			if (!CheckBase ())
635 				return false;
636 
637 			MemberKind kind;
638 			if (this is Operator)
639 				kind = MemberKind.Operator;
640 			else if (this is Destructor)
641 				kind = MemberKind.Destructor;
642 			else
643 				kind = MemberKind.Method;
644 
645 			string explicit_name;
646 
647 			if (IsPartialDefinition) {
648 				caching_flags &= ~Flags.Excluded_Undetected;
649 				caching_flags |= Flags.Excluded;
650 
651 				// Add to member cache only when a partial method implementation has not been found yet
652 				if ((caching_flags & Flags.PartialDefinitionExists) != 0)
653 					return true;
654 
655 				if (IsExplicitImpl)
656 					return true;
657 
658 				explicit_name = null;
659 			} else {
660 				MethodData = new MethodData (this, ModFlags, flags, this);
661 
662 				if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
663 					return false;
664 
665 				explicit_name = MethodData.MetadataName;
666 			}
667 
668 			spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, parameters, ModFlags);
669 			if (MemberName.Arity > 0)
670 				spec.IsGeneric = true;
671 
672 			Parent.MemberCache.AddMember (this, explicit_name, spec);
673 
674 			return true;
675 		}
676 
DoMemberTypeIndependentChecks()677 		protected override void DoMemberTypeIndependentChecks ()
678 		{
679 			base.DoMemberTypeIndependentChecks ();
680 
681 			CheckAbstractAndExtern (block != null);
682 
683 			if ((ModFlags & Modifiers.PARTIAL) != 0) {
684 				for (int i = 0; i < parameters.Count; ++i) {
685 					IParameterData p = parameters.FixedParameters [i];
686 					if ((p.ModFlags & Parameter.Modifier.OUT) != 0) {
687 						Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
688 							GetSignatureForError ());
689 					}
690 
691 					if (p.HasDefaultValue && IsPartialImplementation)
692 						((Parameter) p).Warning_UselessOptionalParameter (Report);
693 				}
694 			}
695 		}
696 
DoMemberTypeDependentChecks()697 		protected override void DoMemberTypeDependentChecks ()
698 		{
699 			base.DoMemberTypeDependentChecks ();
700 
701 			if (MemberType.IsStatic) {
702 				Error_StaticReturnType ();
703 			}
704 
705 			if (MemberType.IsSpecialRuntimeType && Compiler.Settings.StdLib) {
706 				Error_ReturnTypeCantBeRefAny (Location, ReturnType, Report);
707 			}
708 		}
709 
Emit()710 		public override void Emit ()
711 		{
712 			if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
713 				Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder);
714 			if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
715 				Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder);
716 			if ((ModFlags & Modifiers.DEBUGGER_STEP_THROUGH) != 0)
717 				Module.PredefinedAttributes.DebuggerStepThrough.EmitAttribute (MethodBuilder);
718 
719 			if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
720 				Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
721 			} else if (ReturnType.HasDynamicElement) {
722 				Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
723 			} else if (ReturnType is ReadOnlyReferenceContainer) {
724 				Module.PredefinedAttributes.IsReadOnly.EmitAttribute (CreateReturnBuilder ().Builder);
725 			}
726 
727 			if (ReturnType.HasNamedTupleElement) {
728 				Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
729 			}
730 
731 			if (OptAttributes != null)
732 				OptAttributes.Emit ();
733 
734 			if (declarative_security != null) {
735 				foreach (var de in declarative_security) {
736 #if STATIC
737 					MethodBuilder.__AddDeclarativeSecurity (de);
738 #else
739 					MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
740 #endif
741 				}
742 			}
743 
744 			//
745 			// Optimization but it also covers cases where we cannot check
746 			// constraints because method is captured into generated class
747 			// and type parameters context is now different
748 			//
749 			if (type_expr != null && !IsCompilerGenerated)
750 				ConstraintChecker.Check (this, member_type, type_expr.Location);
751 
752 			base.Emit ();
753 
754 			if (MethodData != null)
755 				MethodData.Emit (Parent);
756 
757 			if (block != null && block.StateMachine is AsyncTaskStorey) {
758 				var psm = Module.PredefinedAttributes.AsyncStateMachine;
759 				psm.EmitAttribute (MethodBuilder, block.StateMachine);
760 			}
761 
762 			if ((ModFlags & Modifiers.PARTIAL) == 0)
763 				Block = null;
764 		}
765 
Error_ConditionalAttributeIsNotValid()766 		protected void Error_ConditionalAttributeIsNotValid ()
767 		{
768 			Report.Error (577, Location,
769 				"Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
770 				GetSignatureForError ());
771 		}
772 
Error_ReturnTypeCantBeRefAny(Location loc, TypeSpec t, Report Report)773 		public static void Error_ReturnTypeCantBeRefAny (Location loc, TypeSpec t, Report Report)
774 		{
775 			Report.Error (1599, loc, "The return type of `{0}' is not allowed", t.GetSignatureForError ());
776 		}
777 
778 		public bool IsPartialDefinition {
779 			get {
780 				return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
781 			}
782 		}
783 
784 		public bool IsPartialImplementation {
785 			get {
786 				return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
787 			}
788 		}
789 
790 		public override string[] ValidAttributeTargets {
791 			get {
792 				return attribute_targets;
793 			}
794 		}
795 
796 		#region IMethodData Members
797 
798 		bool IMethodData.IsAccessor {
799 			get {
800 				return false;
801 			}
802 		}
803 
804 		public TypeSpec ReturnType {
805 			get {
806 				return MemberType;
807 			}
808 		}
809 
810 		public MemberName MethodName {
811 			get {
812 				return MemberName;
813 			}
814 		}
815 
816 		/// <summary>
817 		/// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
818 		/// </summary>
ConditionalConditions()819 		public override string[] ConditionalConditions ()
820 		{
821 			if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
822 				return null;
823 
824 			if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.Excluded) != 0)
825 				return new string [0];
826 
827 			caching_flags &= ~Flags.Excluded_Undetected;
828 			string[] conditions;
829 
830 			if (base_method == null) {
831 				if (OptAttributes == null)
832 					return null;
833 
834 				Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
835 				if (attrs == null)
836 					return null;
837 
838 				conditions = new string[attrs.Length];
839 				for (int i = 0; i < conditions.Length; ++i)
840 					conditions[i] = attrs[i].GetConditionalAttributeValue ();
841 			} else {
842 				conditions = base_method.MemberDefinition.ConditionalConditions();
843 			}
844 
845 			if (conditions != null)
846 				caching_flags |= Flags.Excluded;
847 
848 			return conditions;
849 		}
850 
851 		#endregion
852 
PrepareEmit()853 		public override void PrepareEmit ()
854 		{
855 			base.PrepareEmit ();
856 
857 			var mb = MethodData.DefineMethodBuilder (Parent);
858 
859 			if (CurrentTypeParameters != null) {
860 				string[] gnames = new string[CurrentTypeParameters.Count];
861 				for (int i = 0; i < gnames.Length; ++i) {
862 					gnames[i] = CurrentTypeParameters[i].Name;
863 				}
864 
865 				var gen_params = MethodBuilder.DefineGenericParameters (gnames);
866 
867 				for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
868 					var tp = CurrentTypeParameters[i];
869 
870 					tp.Define (gen_params[i]);
871 				}
872 			}
873 
874 			//
875 			// Generic method has been already defined to resolve method parameters
876 			// correctly when they use type parameters
877 			//
878 			mb.SetParameters (parameters.GetMetaInfo ());
879 			mb.SetReturnType (ReturnType.GetMetaInfo ());
880 		}
881 
WriteDebugSymbol(MonoSymbolFile file)882 		public override void WriteDebugSymbol (MonoSymbolFile file)
883 		{
884 			if (MethodData != null && !IsPartialDefinition)
885 				MethodData.WriteDebugSymbol (file);
886 		}
887 	}
888 
889 	public class Method : MethodOrOperator, IGenericMethodDefinition
890 	{
891 		Method partialMethodImplementation;
892 
Method(TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, MemberName name, ParametersCompiled parameters, Attributes attrs)893 		public Method (TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, MemberName name, ParametersCompiled parameters, Attributes attrs)
894 			: base (parent, return_type, mod,
895 				parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
896 				parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct | Modifiers.ASYNC :
897 				AllowedModifiersClass | Modifiers.ASYNC,
898 				name, attrs, parameters)
899 		{
900 		}
901 
Method(TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod, MemberName name, ParametersCompiled parameters, Attributes attrs)902 		protected Method (TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
903 					MemberName name, ParametersCompiled parameters, Attributes attrs)
904 			: base (parent, return_type, mod, amod, name, attrs, parameters)
905 		{
906 		}
907 
908 		#region Properties
909 
910 		public override TypeParameters CurrentTypeParameters {
911 			get {
912 				return MemberName.TypeParameters;
913 			}
914 		}
915 
916 		public TypeParameterSpec[] TypeParameters {
917 			get {
918 				return CurrentTypeParameters.Types;
919 			}
920 		}
921 
922 		public int TypeParametersCount {
923 			get {
924 				return CurrentTypeParameters == null ? 0 : CurrentTypeParameters.Count;
925 			}
926 		}
927 
928 		#endregion
929 
Accept(StructuralVisitor visitor)930 		public override void Accept (StructuralVisitor visitor)
931 		{
932 			visitor.Visit (this);
933 		}
934 
Create(TypeDefinition parent, FullNamedExpression returnType, Modifiers mod, MemberName name, ParametersCompiled parameters, Attributes attrs)935 		public static Method Create (TypeDefinition parent, FullNamedExpression returnType, Modifiers mod,
936 				   MemberName name, ParametersCompiled parameters, Attributes attrs)
937 		{
938 			var m = new Method (parent, returnType, mod, name, parameters, attrs);
939 
940 			if ((mod & Modifiers.PARTIAL) != 0) {
941 				const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN |
942 					Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
943 
944 				if ((mod & invalid_partial_mod) != 0) {
945 					m.Report.Error (750, m.Location,
946 						"A partial method cannot define access modifier or any of abstract, extern, new, override, sealed, or virtual modifiers");
947 					mod &= ~invalid_partial_mod;
948 				}
949 
950 				if ((parent.ModFlags & Modifiers.PARTIAL) == 0) {
951 					m.Report.Error (751, m.Location,
952 						"A partial method must be declared within a partial class or partial struct");
953 				}
954 			}
955 
956 			if ((mod & Modifiers.STATIC) == 0 && parameters.HasExtensionMethodType) {
957 				m.Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static",
958 					m.GetSignatureForError ());
959 			}
960 
961 
962 			return m;
963 		}
964 
GetSignatureForError()965 		public override string GetSignatureForError()
966 		{
967 			return base.GetSignatureForError () + parameters.GetSignatureForError ();
968 		}
969 
Error_DuplicateEntryPoint(Method b)970 		void Error_DuplicateEntryPoint (Method b)
971 		{
972 			Report.Error (17, b.Location,
973 				"Program `{0}' has more than one entry point defined: `{1}'",
974 				b.Module.Builder.ScopeName, b.GetSignatureForError ());
975 		}
976 
IsEntryPoint()977 		bool IsEntryPoint ()
978 		{
979 			if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int)
980 				return false;
981 
982 			if (parameters.IsEmpty)
983 				return true;
984 
985 			if (parameters.Count > 1)
986 				return false;
987 
988 			var ac = parameters.Types [0] as ArrayContainer;
989 			return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String &&
990 					(parameters[0].ModFlags & Parameter.Modifier.RefOutMask) == 0;
991 		}
992 
LookupNamespaceOrType(string name, int arity, LookupMode mode, Location loc)993 		public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
994 		{
995 			if (arity == 0) {
996 				var tp = CurrentTypeParameters;
997 				if (tp != null) {
998 					TypeParameter t = tp.Find (name);
999 					if (t != null)
1000 						return new TypeParameterExpr (t, loc);
1001 				}
1002 			}
1003 
1004 			return base.LookupNamespaceOrType (name, arity, mode, loc);
1005 		}
1006 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)1007 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1008 		{
1009 			if (a.Type == pa.Conditional) {
1010 				if (IsExplicitImpl) {
1011 					Error_ConditionalAttributeIsNotValid ();
1012 					return;
1013 				}
1014 
1015 				if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1016 					Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
1017 					return;
1018 				}
1019 
1020 				if (ReturnType.Kind != MemberKind.Void) {
1021 					Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
1022 					return;
1023 				}
1024 
1025 				if (IsInterface) {
1026 					Report.Error (582, Location, "Conditional not valid on interface members");
1027 					return;
1028 				}
1029 
1030 				if (MethodData.implementing != null) {
1031 					Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
1032 					Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
1033 						GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
1034 					return;
1035 				}
1036 
1037 				for (int i = 0; i < parameters.Count; ++i) {
1038 					if ((parameters.FixedParameters [i].ModFlags & Parameter.Modifier.OUT) != 0) {
1039 						Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
1040 						return;
1041 					}
1042 				}
1043 			}
1044 
1045 			if (a.Type == pa.Extension) {
1046 				a.Error_MisusedExtensionAttribute ();
1047 				return;
1048 			}
1049 
1050 			base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1051 		}
1052 
CreateTypeParameters()1053 		void CreateTypeParameters ()
1054 		{
1055 			var tparams = MemberName.TypeParameters;
1056 			var parent_tparams = Parent.TypeParametersAll;
1057 
1058 			for (int i = 0; i < MemberName.Arity; i++) {
1059 				string type_argument_name = tparams[i].MemberName.Name;
1060 
1061 				if (block == null) {
1062 					int idx = parameters.GetParameterIndexByName (type_argument_name);
1063 					if (idx >= 0) {
1064 						var b = block;
1065 						if (b == null)
1066 							b = new ToplevelBlock (Compiler, Location);
1067 
1068 						b.Error_AlreadyDeclaredTypeParameter (type_argument_name, parameters[i].Location);
1069 					}
1070 				} else {
1071 					INamedBlockVariable variable = null;
1072 					block.GetLocalName (type_argument_name, block, ref variable);
1073 					if (variable != null)
1074 						variable.Block.Error_AlreadyDeclaredTypeParameter (type_argument_name, variable.Location);
1075 				}
1076 
1077 				if (parent_tparams != null) {
1078 					var tp = parent_tparams.Find (type_argument_name);
1079 					if (tp != null) {
1080 						tparams[i].WarningParentNameConflict (tp);
1081 					}
1082 				}
1083 			}
1084 
1085 			tparams.Create (null, 0, Parent);
1086 		}
1087 
DefineTypeParameters()1088 		protected virtual void DefineTypeParameters ()
1089 		{
1090 			var tparams = CurrentTypeParameters;
1091 
1092 			TypeParameterSpec[] base_tparams = null;
1093 			TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes;
1094 			TypeSpec[] base_targs = TypeSpec.EmptyTypes;
1095 			if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
1096 				MethodSpec base_override = base_method ?? MethodData.implementing;
1097 
1098 				if (base_override != null) {
1099 					base_tparams = base_override.GenericDefinition.TypeParameters;
1100 
1101 					if (base_override.DeclaringType.IsGeneric) {
1102 						base_decl_tparams = base_override.DeclaringType.MemberDefinition.TypeParameters;
1103 
1104 						if (base_method != null) {
1105 							var base_type_parent = CurrentType;
1106 							while (base_type_parent.BaseType != base_override.DeclaringType) {
1107 								base_type_parent = base_type_parent.BaseType;
1108 							}
1109 
1110 							base_targs = base_type_parent.BaseType.TypeArguments;
1111 						} else {
1112 							foreach (var iface in Parent.CurrentType.Interfaces) {
1113 								if (iface == base_override.DeclaringType) {
1114 									base_targs = iface.TypeArguments;
1115 									break;
1116 								}
1117 							}
1118 						}
1119 					}
1120 
1121 					if (base_override.IsGeneric) {
1122 						foreach (var base_tp in base_tparams) {
1123 							base_tp.BaseType.CheckObsoleteness (this, Location);
1124 
1125 							if (base_tp.InterfacesDefined != null) {
1126 								foreach (var iface in base_tp.InterfacesDefined) {
1127 									iface.CheckObsoleteness (this, Location);
1128 								}
1129 							}
1130 						}
1131 
1132 						if (base_decl_tparams.Length != 0) {
1133 							base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray ();
1134 							base_targs = base_targs.Concat (tparams.Types).ToArray ();
1135 						} else {
1136 							base_decl_tparams = base_tparams;
1137 							base_targs = tparams.Types;
1138 						}
1139 					}
1140 				}
1141 			}
1142 
1143 			for (int i = 0; i < tparams.Count; ++i) {
1144 				var tp = tparams [i];
1145 
1146 				if (base_tparams == null) {
1147 					tp.ResolveConstraints (this);
1148 					continue;
1149 				}
1150 
1151 				//
1152 				// Copy base constraints for override/explicit methods
1153 				//
1154 				var base_tparam = base_tparams [i];
1155 				var local_tparam = tp.Type;
1156 				local_tparam.SpecialConstraint = base_tparam.SpecialConstraint;
1157 
1158 				var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs);
1159 				base_tparam.InflateConstraints (inflator, local_tparam);
1160 
1161 				//
1162 				// Check all type argument constraints for possible collision or unification
1163 				// introduced by inflating inherited constraints in this context
1164 				//
1165 				// Conflict example:
1166 				//
1167 				// class A<T> { virtual void Foo<U> () where U : class, T {} }
1168 				// class B : A<int> { override void Foo<U> {} }
1169 				//
1170 				var local_tparam_targs = local_tparam.TypeArguments;
1171 				if (local_tparam_targs != null) {
1172 					for (int ii = 0; ii < local_tparam_targs.Length; ++ii) {
1173 						var ta = local_tparam_targs [ii];
1174 						if (!ta.IsClass && !ta.IsStruct)
1175 							continue;
1176 
1177 						TypeSpec[] unique_tparams = null;
1178 						for (int iii = ii + 1; iii < local_tparam_targs.Length; ++iii) {
1179 							//
1180 							// Remove any identical or unified constraint types
1181 							//
1182 							var tparam_checked = local_tparam_targs [iii];
1183 							if (TypeSpecComparer.IsEqual (ta, tparam_checked) || TypeSpec.IsBaseClass (ta, tparam_checked, false)) {
1184 								unique_tparams = new TypeSpec[local_tparam_targs.Length - 1];
1185 								Array.Copy (local_tparam_targs, 0, unique_tparams, 0, iii);
1186 								Array.Copy (local_tparam_targs, iii + 1, unique_tparams, iii, local_tparam_targs.Length - iii - 1);
1187 							} else if (!TypeSpec.IsBaseClass (tparam_checked, ta, false)) {
1188 								Constraints.Error_ConflictingConstraints (this, local_tparam, ta, tparam_checked, Location);
1189 							}
1190 						}
1191 
1192 						if (unique_tparams != null) {
1193 							local_tparam_targs = unique_tparams;
1194 							local_tparam.TypeArguments = local_tparam_targs;
1195 							continue;
1196 						}
1197 
1198 						Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location);
1199 					}
1200 				}
1201 			}
1202 
1203 			if (base_tparams == null && MethodData != null && MethodData.implementing != null) {
1204 				CheckImplementingMethodConstraints (Parent, spec, MethodData.implementing);
1205 			}
1206 		}
1207 
CheckImplementingMethodConstraints(TypeContainer container, MethodSpec method, MethodSpec baseMethod)1208 		public static bool CheckImplementingMethodConstraints (TypeContainer container, MethodSpec method, MethodSpec baseMethod)
1209 		{
1210 			var tparams = method.Constraints;
1211 			var base_tparams = baseMethod.Constraints;
1212 			for (int i = 0; i < tparams.Length; ++i) {
1213 				if (!tparams[i].HasSameConstraintsImplementation (base_tparams[i])) {
1214 					container.Compiler.Report.SymbolRelatedToPreviousError (method);
1215 					container.Compiler.Report.SymbolRelatedToPreviousError (baseMethod);
1216 
1217 					// Using container location because the interface can be implemented
1218 					// by base class
1219 					var tp = (tparams [i].MemberDefinition as MemberCore) ?? container;
1220 					container.Compiler.Report.Error (425, tp.Location,
1221 						"The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead",
1222 						tparams[i].GetSignatureForError (), method.GetSignatureForError (),
1223 						base_tparams[i].GetSignatureForError (), baseMethod.GetSignatureForError ());
1224 
1225 					return false;
1226 				}
1227 			}
1228 
1229 			return true;
1230 		}
1231 
1232 		//
1233 		// Creates the type
1234 		//
Define()1235 		public override bool Define ()
1236 		{
1237 			if (!base.Define ())
1238 				return false;
1239 
1240 			if (member_type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
1241 				Report.Warning (465, 1, Location,
1242 					"Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
1243 			}
1244 
1245 			if (CurrentTypeParameters == null) {
1246 				if (base_method != null && !IsExplicitImpl) {
1247 					if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && MemberName.Name == "Equals")
1248 						Parent.PartialContainer.Mark_HasEquals ();
1249 					else if (parameters.IsEmpty && MemberName.Name == "GetHashCode")
1250 						Parent.PartialContainer.Mark_HasGetHashCode ();
1251 				}
1252 
1253 			} else {
1254 				DefineTypeParameters ();
1255 			}
1256 
1257 			if (block != null) {
1258 				if (block.IsIterator) {
1259 					//
1260 					// Current method is turned into automatically generated
1261 					// wrapper which creates an instance of iterator
1262 					//
1263 					Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1264 					ModFlags |= Modifiers.DEBUGGER_HIDDEN;
1265 				}
1266 
1267 				if ((ModFlags & Modifiers.ASYNC) != 0) {
1268 					if (ReturnType.Kind != MemberKind.Void &&
1269 						ReturnType != Module.PredefinedTypes.Task.TypeSpec &&
1270 						!ReturnType.IsGenericTask &&
1271 					    !ReturnType.IsCustomTaskType ()) {
1272 						Report.Error (1983, Location, "The return type of an async method must be void or task type");
1273 					}
1274 
1275 					block = (ToplevelBlock) block.ConvertToAsyncTask (this, Parent.PartialContainer, parameters, ReturnType, null, Location);
1276 					ModFlags |= Modifiers.DEBUGGER_STEP_THROUGH;
1277 				}
1278 
1279 				if (Compiler.Settings.WriteMetadataOnly)
1280 					block = null;
1281 			}
1282 
1283 			if ((ModFlags & Modifiers.STATIC) == 0)
1284 				return true;
1285 
1286 			if (parameters.HasExtensionMethodType) {
1287 				if (Parent.PartialContainer.IsStatic && !Parent.IsGenericOrParentIsGeneric) {
1288 					if (!Parent.IsTopLevel)
1289 						Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
1290 							GetSignatureForError ());
1291 
1292 					PredefinedAttribute pa = Module.PredefinedAttributes.Extension;
1293 					if (!pa.IsDefined) {
1294 						Report.Error (1110, Location,
1295 							"`{0}': Extension methods require `System.Runtime.CompilerServices.ExtensionAttribute' type to be available. Are you missing an assembly reference?",
1296 							GetSignatureForError ());
1297 					}
1298 
1299 					ModFlags |= Modifiers.METHOD_EXTENSION;
1300 					Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
1301 					Spec.DeclaringType.SetExtensionMethodContainer ();
1302 					Parent.Module.HasExtensionMethod = true;
1303 				} else {
1304 					Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
1305 						GetSignatureForError ());
1306 				}
1307 			}
1308 
1309 			//
1310 			// This is used to track the Entry Point,
1311 			//
1312 			var settings = Compiler.Settings;
1313 			if (settings.NeedsEntryPoint && MemberName.Name == "Main" && !IsPartialDefinition && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) {
1314 				if (IsEntryPoint ()) {
1315 					if (Parent.DeclaringAssembly.EntryPoint == null) {
1316 						if (Parent.IsGenericOrParentIsGeneric || MemberName.IsGeneric) {
1317 							Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
1318 								GetSignatureForError ());
1319 						} else if ((ModFlags & Modifiers.ASYNC) != 0) {
1320 							Report.Error (4009, Location, "`{0}': an entry point cannot be async method",
1321 								GetSignatureForError ());
1322 						} else {
1323 							SetIsUsed ();
1324 							Parent.DeclaringAssembly.EntryPoint = this;
1325 						}
1326 					} else {
1327 						Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint);
1328 						Error_DuplicateEntryPoint (this);
1329 					}
1330 				} else {
1331 					Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
1332 						GetSignatureForError ());
1333 				}
1334 			}
1335 
1336 			return true;
1337 		}
1338 
PrepareEmit()1339 		public override void PrepareEmit ()
1340 		{
1341 			if (IsPartialDefinition) {
1342 				//
1343 				// Use partial method implementation builder for partial method declaration attributes
1344 				//
1345 				if (partialMethodImplementation != null) {
1346 					MethodData = partialMethodImplementation.MethodData;
1347 				}
1348 
1349 				return;
1350 			}
1351 
1352 			base.PrepareEmit ();
1353 		}
1354 
1355 		//
1356 		// Emits the code
1357 		//
Emit()1358 		public override void Emit ()
1359 		{
1360 			try {
1361 				if (IsPartialDefinition) {
1362 					if (partialMethodImplementation != null && CurrentTypeParameters != null) {
1363 						CurrentTypeParameters.CheckPartialConstraints (partialMethodImplementation);
1364 
1365 						var otp = partialMethodImplementation.CurrentTypeParameters;
1366 						for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1367 							var tp = CurrentTypeParameters [i];
1368 							tp.Define (otp[i]);
1369 						}
1370 					}
1371 
1372 					return;
1373 				}
1374 
1375 				if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
1376 					Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
1377 						GetSignatureForError ());
1378 				}
1379 
1380 				if (CurrentTypeParameters != null) {
1381 					for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1382 						var tp = CurrentTypeParameters [i];
1383 
1384 						tp.CheckGenericConstraints (false);
1385 						tp.Emit ();
1386 					}
1387 				}
1388 
1389 				if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
1390 					Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder);
1391 
1392 				base.Emit ();
1393 			} catch (Exception e) {
1394 				throw new InternalErrorException (this, e);
1395 			}
1396 		}
1397 
EnableOverloadChecks(MemberCore overload)1398 		public override bool EnableOverloadChecks (MemberCore overload)
1399 		{
1400 			if (overload is Indexer)
1401 				return false;
1402 
1403 			return base.EnableOverloadChecks (overload);
1404 		}
1405 
ResolveMemberType()1406 		protected override bool ResolveMemberType ()
1407 		{
1408 			if (CurrentTypeParameters != null) {
1409 				CreateTypeParameters ();
1410 			}
1411 
1412 			return base.ResolveMemberType ();
1413 		}
1414 
SetPartialDefinition(Method methodDefinition)1415 		public void SetPartialDefinition (Method methodDefinition)
1416 		{
1417 			caching_flags |= Flags.PartialDefinitionExists;
1418 			methodDefinition.partialMethodImplementation = this;
1419 
1420 			// Ensure we are always using method declaration parameters
1421 			for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1422 				var md_p = methodDefinition.parameters [i];
1423 				var p = parameters [i];
1424 				p.Name = md_p.Name;
1425 				p.DefaultValue = md_p.DefaultValue;
1426 				if (md_p.OptAttributes != null) {
1427 					Attributes.AttachFromPartial (p, md_p);
1428 				}
1429 			}
1430 
1431 			if (methodDefinition.attributes != null) {
1432 				if (attributes == null) {
1433 					attributes = methodDefinition.attributes;
1434 				} else {
1435 					attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1436 				}
1437 			}
1438 
1439 			if (CurrentTypeParameters != null) {
1440 				for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1441 					var tp_other = methodDefinition.CurrentTypeParameters [i];
1442 					if (tp_other.OptAttributes == null)
1443 						continue;
1444 
1445 					var tp = CurrentTypeParameters [i];
1446 					if (tp.OptAttributes == null) {
1447 						tp.OptAttributes = tp_other.OptAttributes;
1448 					} else {
1449 						tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1450 					}
1451 				}
1452 			}
1453 		}
1454 	}
1455 
1456 	public abstract class ConstructorInitializer : ExpressionStatement
1457 	{
1458 		Arguments argument_list;
1459 		MethodSpec base_ctor;
1460 
ConstructorInitializer(Arguments argument_list, Location loc)1461 		protected ConstructorInitializer (Arguments argument_list, Location loc)
1462 		{
1463 			this.argument_list = argument_list;
1464 			this.loc = loc;
1465 		}
1466 
1467 		public Arguments Arguments {
1468 			get {
1469 				return argument_list;
1470 			}
1471 		}
1472 
ContainsEmitWithAwait()1473 		public override bool ContainsEmitWithAwait ()
1474 		{
1475 			throw new NotSupportedException ();
1476 		}
1477 
CreateExpressionTree(ResolveContext ec)1478 		public override Expression CreateExpressionTree (ResolveContext ec)
1479 		{
1480 			throw new NotSupportedException ("ET");
1481 		}
1482 
DoResolve(ResolveContext ec)1483 		protected override Expression DoResolve (ResolveContext ec)
1484 		{
1485 			eclass = ExprClass.Value;
1486 
1487 			// FIXME: Hack
1488 			var caller_builder = (Constructor) ec.MemberContext;
1489 
1490 			//
1491 			// Spec mandates that constructor initializer will not have `this' access
1492 			//
1493 			using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1494 				if (argument_list != null) {
1495 					bool dynamic;
1496 					argument_list.Resolve (ec, out dynamic);
1497 
1498 					if (dynamic) {
1499 						ec.Report.Error (1975, loc,
1500 							"The constructor call cannot be dynamically dispatched within constructor initializer");
1501 
1502 						return null;
1503 					}
1504 				}
1505 
1506 				type = ec.CurrentType;
1507 				if (this is ConstructorBaseInitializer) {
1508 					if (ec.CurrentType.BaseType == null)
1509 						return this;
1510 
1511 					type = ec.CurrentType.BaseType;
1512 					if (ec.CurrentType.IsStruct) {
1513 						ec.Report.Error (522, loc,
1514 							"`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1515 						return this;
1516 					}
1517 				}
1518 
1519 				base_ctor = ConstructorLookup (ec, type, ref argument_list, loc);
1520 			}
1521 
1522 			if (base_ctor != null && base_ctor.MemberDefinition == caller_builder.Spec.MemberDefinition) {
1523 				ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1524 					caller_builder.GetSignatureForError ());
1525 			}
1526 
1527 			return this;
1528 		}
1529 
Emit(EmitContext ec)1530 		public override void Emit (EmitContext ec)
1531 		{
1532 			//
1533 			// It can be null for struct initializers or System.Object
1534 			//
1535 			if (base_ctor == null) {
1536 				if (type == ec.BuiltinTypes.Object)
1537 					return;
1538 
1539 				ec.Emit (OpCodes.Ldarg_0);
1540 				ec.Emit (OpCodes.Initobj, type);
1541 				return;
1542 			}
1543 
1544 			var call = new CallEmitter ();
1545 			call.InstanceExpression = new CompilerGeneratedThis (type, loc);
1546 			call.EmitPredefined (ec, base_ctor, argument_list, false);
1547 		}
1548 
EmitStatement(EmitContext ec)1549 		public override void EmitStatement (EmitContext ec)
1550 		{
1551 			Emit (ec);
1552 		}
1553 
FlowAnalysis(FlowAnalysisContext fc)1554 		public override void FlowAnalysis (FlowAnalysisContext fc)
1555 		{
1556 			if (argument_list != null)
1557 				argument_list.FlowAnalysis (fc);
1558 		}
1559 	}
1560 
1561 	public class ConstructorBaseInitializer : ConstructorInitializer {
ConstructorBaseInitializer(Arguments argument_list, Location l)1562 		public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1563 			base (argument_list, l)
1564 		{
1565 		}
1566 	}
1567 
1568 	class GeneratedBaseInitializer: ConstructorBaseInitializer {
GeneratedBaseInitializer(Location loc, Arguments arguments)1569 		public GeneratedBaseInitializer (Location loc, Arguments arguments)
1570 			: base (arguments, loc)
1571 		{
1572 		}
1573 	}
1574 
1575 	public class ConstructorThisInitializer : ConstructorInitializer {
ConstructorThisInitializer(Arguments argument_list, Location l)1576 		public ConstructorThisInitializer (Arguments argument_list, Location l) :
1577 			base (argument_list, l)
1578 		{
1579 		}
1580 	}
1581 
1582 	public class Constructor : MethodCore, IMethodData, IMethodDefinition
1583 	{
1584 		public ConstructorBuilder ConstructorBuilder;
1585 		public ConstructorInitializer Initializer;
1586 		SecurityType declarative_security;
1587 		bool has_compliant_args;
1588 		SourceMethodBuilder debug_builder;
1589 
1590 		// <summary>
1591 		//   Modifiers allowed for a constructor.
1592 		// </summary>
1593 		public const Modifiers AllowedModifiers =
1594 			Modifiers.PUBLIC |
1595 			Modifiers.PROTECTED |
1596 			Modifiers.INTERNAL |
1597 			Modifiers.STATIC |
1598 			Modifiers.UNSAFE |
1599 			Modifiers.EXTERN |
1600 			Modifiers.PRIVATE;
1601 
1602 		static readonly string[] attribute_targets = new string [] { "method" };
1603 
1604 		public static readonly string ConstructorName = ".ctor";
1605 		public static readonly string TypeConstructorName = ".cctor";
1606 
Constructor(TypeDefinition parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, Location loc)1607 		public Constructor (TypeDefinition parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, Location loc)
1608 			: base (parent, null, mod, AllowedModifiers, new MemberName (name, loc), attrs, args)
1609 		{
1610 		}
1611 
1612 		public bool HasCompliantArgs {
1613 			get {
1614 				return has_compliant_args;
1615 			}
1616 		}
1617 
1618 		public override AttributeTargets AttributeTargets {
1619 			get {
1620 				return AttributeTargets.Constructor;
1621 			}
1622 		}
1623 
1624 		bool IMethodData.IsAccessor {
1625 		    get {
1626 		        return false;
1627 		    }
1628 		}
1629 
1630 		public bool IsPrimaryConstructor { get; set; }
1631 
1632 		MethodBase IMethodDefinition.Metadata {
1633 			get {
1634 				return ConstructorBuilder;
1635 			}
1636 		}
1637 
1638 		//
1639 		// Returns true if this is a default constructor
1640 		//
IsDefault()1641 		public bool IsDefault ()
1642 		{
1643 			if ((ModFlags & Modifiers.STATIC) != 0)
1644 				return parameters.IsEmpty;
1645 
1646 			return parameters.IsEmpty &&
1647 					(Initializer is ConstructorBaseInitializer) &&
1648 					(Initializer.Arguments == null);
1649 		}
1650 
Accept(StructuralVisitor visitor)1651 		public override void Accept (StructuralVisitor visitor)
1652 		{
1653 			visitor.Visit (this);
1654 		}
1655 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)1656 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1657 		{
1658 			if (a.IsValidSecurityAttribute ()) {
1659 				a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
1660 				return;
1661 			}
1662 
1663 			if (a.Type == pa.MethodImpl) {
1664 				is_external_implementation = a.IsInternalCall ();
1665 			}
1666 
1667 			ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1668 		}
1669 
CheckBase()1670 		protected override bool CheckBase ()
1671 		{
1672 			if ((ModFlags & Modifiers.STATIC) != 0) {
1673 				if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1674 					Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1675 
1676 				// the rest can be ignored
1677 				return true;
1678 			}
1679 
1680 			// Check whether arguments were correct.
1681 			if (!DefineParameters (parameters))
1682 				return false;
1683 
1684 			if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1685 				Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1686 
1687 			CheckProtectedModifier ();
1688 
1689 			return true;
1690 		}
1691 
1692 		//
1693 		// Creates the ConstructorBuilder
1694 		//
Define()1695 		public override bool Define ()
1696 		{
1697 			if (ConstructorBuilder != null)
1698 				return true;
1699 
1700 			if (!CheckAbstractAndExtern (block != null))
1701 				return false;
1702 
1703 			// Check if arguments were correct.
1704 			if (!CheckBase ())
1705 				return false;
1706 
1707 			if (Parent.PrimaryConstructorParameters != null && !IsPrimaryConstructor && !IsStatic) {
1708 				if (Parent.Kind == MemberKind.Struct && Initializer is ConstructorThisInitializer && Initializer.Arguments == null) {
1709 					Report.Error (8043, Location, "`{0}': Structs with primary constructor cannot specify default constructor initializer",
1710 						GetSignatureForError ());
1711 				} else if (Initializer == null || Initializer is ConstructorBaseInitializer) {
1712 					Report.Error (8037, Location, "`{0}': Instance constructor of type with primary constructor must specify `this' constructor initializer",
1713 						GetSignatureForError ());
1714 				}
1715 			}
1716 
1717 			if ((ModFlags & Modifiers.EXTERN) != 0 && Initializer != null) {
1718 				Report.Error (8091, Location, "`{0}': Contructors cannot be extern and have a constructor initializer",
1719 					GetSignatureForError ());
1720 			}
1721 
1722 			var ca = ModifiersExtensions.MethodAttr (ModFlags) | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1723 
1724 			ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1725 				ca, CallingConventions,
1726 				parameters.GetMetaInfo ());
1727 
1728 			spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, parameters, ModFlags);
1729 
1730 			Parent.MemberCache.AddMember (spec);
1731 
1732 			if (block != null) {
1733 				// It's here only to report an error
1734 				if (block.IsIterator) {
1735 					member_type = Compiler.BuiltinTypes.Void;
1736 					Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1737 				}
1738 
1739 				if (Compiler.Settings.WriteMetadataOnly)
1740 					block = null;
1741 			}
1742 
1743 			return true;
1744 		}
1745 
1746 		//
1747 		// Emits the code
1748 		//
Emit()1749 		public override void Emit ()
1750 		{
1751 			if (Parent.PartialContainer.IsComImport) {
1752 				if (!IsDefault ()) {
1753 					Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1754 						Parent.GetSignatureForError ());
1755 				}
1756 
1757 				// Set as internal implementation and reset block data
1758 				// to ensure no IL is generated
1759 				ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1760 				block = null;
1761 			}
1762 
1763 			if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1764 				Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1765 
1766 			if (OptAttributes != null)
1767 				OptAttributes.Emit ();
1768 
1769 			base.Emit ();
1770 			parameters.ApplyAttributes (this, ConstructorBuilder);
1771 
1772 
1773 			BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void);
1774 			bc.Set (ResolveContext.Options.ConstructorScope);
1775 
1776 			if (block != null) {
1777 				if (!IsStatic && Initializer == null && Parent.PartialContainer.Kind == MemberKind.Struct) {
1778 					//
1779 					// If this is a non-static `struct' constructor and doesn't have any
1780 					// initializer, it must initialize all of the struct's fields.
1781 					//
1782 					block.AddThisVariable (bc);
1783 				}
1784 
1785 				//
1786 				// If we use a "this (...)" constructor initializer, then
1787 				// do not emit field initializers, they are initialized in the other constructor
1788 				//
1789 				if (!(Initializer is ConstructorThisInitializer)) {
1790 					var errors = Compiler.Report.Errors;
1791 					Parent.PartialContainer.ResolveFieldInitializers (bc);
1792 					if (errors != Compiler.Report.Errors)
1793 						return;
1794 				}
1795 
1796 				if (!IsStatic) {
1797 					if (Initializer == null && Parent.PartialContainer.Kind == MemberKind.Class) {
1798 						Initializer = new GeneratedBaseInitializer (Location, null);
1799 					}
1800 
1801 					if (Initializer != null) {
1802 						//
1803 						// mdb format does not support reqions. Try to workaround this by emitting the
1804 						// sequence point at initializer. Any breakpoint at constructor header should
1805 						// be adjusted to this sequence point as it's the next one which follows.
1806 						//
1807 						block.AddScopeStatement (new StatementExpression (Initializer));
1808 					}
1809 				}
1810 
1811 				if (block.Resolve (bc, this)) {
1812 					debug_builder = Parent.CreateMethodSymbolEntry ();
1813 					EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType, debug_builder);
1814 					ec.With (EmitContext.Options.ConstructorScope, true);
1815 
1816 					block.Emit (ec);
1817 				}
1818 			}
1819 
1820 			if (declarative_security != null) {
1821 				foreach (var de in declarative_security) {
1822 #if STATIC
1823 					ConstructorBuilder.__AddDeclarativeSecurity (de);
1824 #else
1825 					ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1826 #endif
1827 				}
1828 			}
1829 
1830 			block = null;
1831 		}
1832 
FindBaseMember(out MemberSpec bestCandidate, ref bool overrides)1833 		protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
1834 		{
1835 			// Is never override
1836 			bestCandidate = null;
1837 			return null;
1838 		}
1839 
GetCallerMemberName()1840 		public override string GetCallerMemberName ()
1841 		{
1842 			return IsStatic ? TypeConstructorName : ConstructorName;
1843 		}
1844 
GetSignatureForDocumentation()1845 		public override string GetSignatureForDocumentation ()
1846 		{
1847 			return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation ();
1848 		}
1849 
GetSignatureForError()1850 		public override string GetSignatureForError()
1851 		{
1852 			return base.GetSignatureForError () + parameters.GetSignatureForError ();
1853 		}
1854 
1855 		public override string[] ValidAttributeTargets {
1856 			get {
1857 				return attribute_targets;
1858 			}
1859 		}
1860 
VerifyClsCompliance()1861 		protected override bool VerifyClsCompliance ()
1862 		{
1863 			if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1864 				return false;
1865 			}
1866 
1867 			if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1868 				foreach (TypeSpec param in parameters.Types) {
1869 					if (param.IsArray) {
1870 						return true;
1871 					}
1872 				}
1873 			}
1874 
1875 			has_compliant_args = true;
1876 			return true;
1877 		}
1878 
WriteDebugSymbol(MonoSymbolFile file)1879 		public override void WriteDebugSymbol (MonoSymbolFile file)
1880 		{
1881 			if (debug_builder == null)
1882 				return;
1883 
1884 #if !FULL_AOT_RUNTIME
1885 			var token = ConstructorBuilder.GetToken ();
1886 			int t = token.Token;
1887 #if STATIC
1888 			if (ModuleBuilder.IsPseudoToken (t))
1889 				t = Module.Builder.ResolvePseudoToken (t);
1890 #endif
1891 
1892 			debug_builder.DefineMethod (file, t);
1893 #endif
1894 		}
1895 
1896 		#region IMethodData Members
1897 
1898 		public MemberName MethodName {
1899 			get {
1900 				return MemberName;
1901 			}
1902 		}
1903 
1904 		public TypeSpec ReturnType {
1905 			get {
1906 				return MemberType;
1907 			}
1908 		}
1909 
IMethodData.CreateEmitContext(ILGenerator ig, SourceMethodBuilder sourceMethod)1910 		EmitContext IMethodData.CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
1911 		{
1912 			throw new NotImplementedException ();
1913 		}
1914 
1915 		#endregion
1916 	}
1917 
1918 	/// <summary>
1919 	/// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1920 	/// </summary>
1921 	public interface IMethodData : IMemberContext
1922 	{
1923 		CallingConventions CallingConventions { get; }
1924 		Location Location { get; }
1925 		MemberName MethodName { get; }
1926 		TypeSpec ReturnType { get; }
1927 		ParametersCompiled ParameterInfo { get; }
1928 		MethodSpec Spec { get; }
1929 		bool IsAccessor { get; }
1930 
1931 		Attributes OptAttributes { get; }
1932 		ToplevelBlock Block { get; set; }
1933 
CreateEmitContext(ILGenerator ig, SourceMethodBuilder sourceMethod)1934 		EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod);
1935 	}
1936 
1937 	//
1938 	// Encapsulates most of the Method's state
1939 	//
1940 	public class MethodData
1941 	{
1942 		public readonly IMethodData method;
1943 
1944 		//
1945 		// Are we implementing an interface ?
1946 		//
1947 		public MethodSpec implementing;
1948 
1949 		//
1950 		// Protected data.
1951 		//
1952 		protected InterfaceMemberBase member;
1953 		protected Modifiers modifiers;
1954 		protected MethodAttributes flags;
1955 		protected TypeSpec declaring_type;
1956 		SourceMethodBuilder debug_builder;
1957 		string full_name;
1958 
1959 		MethodBuilder builder;
1960 		public MethodBuilder MethodBuilder {
1961 			get {
1962 				return builder;
1963 			}
1964 		}
1965 
1966 		public TypeSpec DeclaringType {
1967 			get {
1968 				return declaring_type;
1969 			}
1970 		}
1971 
1972 		public string MetadataName {
1973 			get {
1974 				return full_name;
1975 			}
1976 		}
1977 
MethodData(InterfaceMemberBase member, Modifiers modifiers, MethodAttributes flags, IMethodData method)1978 		public MethodData (InterfaceMemberBase member,
1979 				   Modifiers modifiers, MethodAttributes flags, IMethodData method)
1980 		{
1981 			this.member = member;
1982 			this.modifiers = modifiers;
1983 			this.flags = flags;
1984 
1985 			this.method = method;
1986 		}
1987 
Define(TypeDefinition container, string method_full_name)1988 		public bool Define (TypeDefinition container, string method_full_name)
1989 		{
1990 			PendingImplementation pending = container.PendingImplementations;
1991 			MethodSpec ambig_iface_method;
1992 			bool optional = false;
1993 
1994 			if (pending != null) {
1995 				implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method, ref optional);
1996 
1997 				if (member.InterfaceType != null) {
1998 					if (implementing == null) {
1999 						if (member is PropertyBase) {
2000 							container.Compiler.Report.Error (550, method.Location,
2001 								"`{0}' is an accessor not found in interface member `{1}{2}'",
2002 									  method.GetSignatureForError (), member.InterfaceType.GetSignatureForError (),
2003 									  member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
2004 
2005 						} else {
2006 							container.Compiler.Report.Error (539, method.Location,
2007 									  "`{0}.{1}' in explicit interface declaration is not a member of interface",
2008 									  member.InterfaceType.GetSignatureForError (), member.ShortName);
2009 						}
2010 						return false;
2011 					}
2012 					if (implementing.IsAccessor && !method.IsAccessor) {
2013 						container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2014 						container.Compiler.Report.Error (683, method.Location,
2015 							"`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
2016 							member.GetSignatureForError (), implementing.GetSignatureForError ());
2017 						return false;
2018 					}
2019 				} else {
2020 					if (implementing != null && !optional) {
2021 						if (!method.IsAccessor) {
2022 							if (implementing.IsAccessor) {
2023 								container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2024 								container.Compiler.Report.Error (470, method.Location,
2025 									"Method `{0}' cannot implement interface accessor `{1}'",
2026 									method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
2027 							}
2028 						} else if (implementing.DeclaringType.IsInterface) {
2029 							if (!implementing.IsAccessor) {
2030 								container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2031 								container.Compiler.Report.Error (686, method.Location,
2032 									"Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
2033 									method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
2034 							} else {
2035 								PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod;
2036 								if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
2037 									container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2038 									container.Compiler.Report.Error (277, method.Location,
2039 										"Accessor `{0}' must be declared public to implement interface member `{1}'",
2040 										method.GetSignatureForError (), implementing.GetSignatureForError ());
2041 								}
2042 							}
2043 						}
2044 
2045 						if (!NamedTupleSpec.CheckOverrideName (member.MemberType, implementing.ReturnType)) {
2046 							container.Compiler.Report.Error (8141, method.Location,
2047 								"The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
2048 								member.GetSignatureForError (), implementing.GetSignatureForError ());
2049 						}
2050 
2051 						var p_member = method as IParametersMember;
2052 						var p_implementing = implementing as IParametersMember;
2053 						if (p_member != null && p_implementing != null && !NamedTupleSpec.CheckOverrideName (p_member, p_implementing)) {
2054 							container.Compiler.Report.Error (8141, method.Location,
2055 								"The tuple element names in the signature type of member `{0}' must match the tuple element names of interface member `{1}''",
2056 								member.GetSignatureForError (), implementing.GetSignatureForError ());
2057 						}
2058 					}
2059 				}
2060 			} else {
2061 				ambig_iface_method = null;
2062 			}
2063 
2064 			//
2065 			// For implicit implementations, make sure we are public, for
2066 			// explicit implementations, make sure we are private.
2067 			//
2068 			if (implementing != null){
2069 				if (member.IsExplicitImpl) {
2070 					if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
2071 						container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2072 						container.Compiler.Report.Error (466, method.Location,
2073 							"`{0}': the explicit interface implementation cannot introduce the params modifier",
2074 							method.GetSignatureForError ());
2075 					}
2076 
2077 					if (ambig_iface_method != null) {
2078 						container.Compiler.Report.SymbolRelatedToPreviousError (ambig_iface_method);
2079 						container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
2080 						container.Compiler.Report.Warning (473, 2, method.Location,
2081 							"Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead",
2082 							method.GetSignatureForError ());
2083 					}
2084 				} else {
2085 					//
2086 					// Setting implementing to null inside this block will trigger a more
2087 					// verbose error reporting for missing interface implementations
2088 					//
2089 					if (implementing.DeclaringType.IsInterface) {
2090 						//
2091 						// If this is an interface method implementation,
2092 						// check for public accessibility
2093 						//
2094 						if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) {
2095 							implementing = null;
2096 						} else if (optional && (container.Interfaces == null || !container.Definition.Interfaces.Contains (implementing.DeclaringType))) {
2097 							//
2098 							// We are not implementing interface when base class already implemented it
2099 							//
2100 							implementing = null;
2101 						}
2102 					} else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
2103 						// We may never be private.
2104 						implementing = null;
2105 
2106 					} else if ((modifiers & Modifiers.OVERRIDE) == 0) {
2107 						//
2108 						// We may be protected if we're overriding something.
2109 						//
2110 						implementing = null;
2111 					}
2112 				}
2113 
2114 				//
2115 				// Static is not allowed
2116 				//
2117 				if ((modifiers & Modifiers.STATIC) != 0){
2118 					implementing = null;
2119 				}
2120 			}
2121 
2122 			//
2123 			// If implementing is still valid, set flags
2124 			//
2125 			if (implementing != null){
2126 				//
2127 				// When implementing interface methods, set NewSlot
2128 				// unless, we are overwriting a method.
2129 				//
2130 				if ((modifiers & Modifiers.OVERRIDE) == 0 && implementing.DeclaringType.IsInterface) {
2131 					flags |= MethodAttributes.NewSlot;
2132 				}
2133 
2134 				flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
2135 
2136 				// Set Final unless we're virtual, abstract or already overriding a method.
2137 				if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
2138 					flags |= MethodAttributes.Final;
2139 
2140 				//
2141 				// clear the pending implementation flag (requires explicit methods to be defined first)
2142 				//
2143 				pending.ImplementMethod (method.MethodName,
2144 					member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method, ref optional);
2145 
2146 				//
2147 				// Update indexer accessor name to match implementing abstract accessor
2148 				//
2149 				if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
2150 					method_full_name = implementing.MemberDefinition.Name;
2151 			}
2152 
2153 			full_name = method_full_name;
2154 			declaring_type = container.Definition;
2155 
2156 			return true;
2157 		}
2158 
DefineOverride(TypeDefinition container)2159 		void DefineOverride (TypeDefinition container)
2160 		{
2161 			if (implementing == null)
2162 				return;
2163 
2164 			if (!member.IsExplicitImpl)
2165 				return;
2166 
2167 			container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
2168 		}
2169 
2170 		//
2171 		// Creates partial MethodBuilder for the method when has generic parameters used
2172 		// as arguments or return type
2173 		//
DefineMethodBuilder(TypeDefinition container)2174 		public MethodBuilder DefineMethodBuilder (TypeDefinition container)
2175 		{
2176 			if (builder != null)
2177 				throw new InternalErrorException ();
2178 
2179 			builder = container.TypeBuilder.DefineMethod (full_name, flags, method.CallingConventions);
2180 			return builder;
2181 		}
2182 
2183 		//
2184 		// Creates full MethodBuilder for the method
2185 		//
DefineMethodBuilder(TypeDefinition container, ParametersCompiled param)2186 		public MethodBuilder DefineMethodBuilder (TypeDefinition container, ParametersCompiled param)
2187 		{
2188 			DefineMethodBuilder (container);
2189 			builder.SetReturnType (method.ReturnType.GetMetaInfo ());
2190 			builder.SetParameters (param.GetMetaInfo ());
2191 			return builder;
2192 		}
2193 
2194 		//
2195 		// Emits the code
2196 		//
Emit(TypeDefinition parent)2197 		public void Emit (TypeDefinition parent)
2198 		{
2199 			DefineOverride (parent);
2200 
2201 			method.ParameterInfo.ApplyAttributes (method, MethodBuilder);
2202 
2203 			ToplevelBlock block = method.Block;
2204 			if (block != null) {
2205 				BlockContext bc = new BlockContext (method, block, method.ReturnType);
2206 				if (block.Resolve (bc, method)) {
2207 					debug_builder = member.Parent.CreateMethodSymbolEntry ();
2208 					EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator (), debug_builder);
2209 
2210 					block.Emit (ec);
2211 				}
2212 			}
2213 		}
2214 
WriteDebugSymbol(MonoSymbolFile file)2215 		public void WriteDebugSymbol (MonoSymbolFile file)
2216 		{
2217 			if (debug_builder == null)
2218 				return;
2219 
2220 #if !FULL_AOT_RUNTIME
2221 			var token = builder.GetToken ();
2222 			int t = token.Token;
2223 #if STATIC
2224 			if (ModuleBuilder.IsPseudoToken (t))
2225 				t = member.Module.Builder.ResolvePseudoToken (t);
2226 #endif
2227 
2228 			debug_builder.DefineMethod (file, t);
2229 #endif
2230 		}
2231 	}
2232 
2233 	public class Destructor : MethodOrOperator
2234 	{
2235 		const Modifiers AllowedModifiers =
2236 			Modifiers.UNSAFE |
2237 			Modifiers.EXTERN;
2238 
2239 		static readonly string[] attribute_targets = new string [] { "method" };
2240 
2241 		public static readonly string MetadataName = "Finalize";
2242 
Destructor(TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)2243 		public Destructor (TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
2244 			: base (parent, null, mod, AllowedModifiers, new MemberName (MetadataName, l), attrs, parameters)
2245 		{
2246 			ModFlags &= ~Modifiers.PRIVATE;
2247 			ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
2248 		}
2249 
Accept(StructuralVisitor visitor)2250 		public override void Accept (StructuralVisitor visitor)
2251 		{
2252 			visitor.Visit (this);
2253 		}
2254 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)2255 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2256 		{
2257 			if (a.Type == pa.Conditional) {
2258 				Error_ConditionalAttributeIsNotValid ();
2259 				return;
2260 			}
2261 
2262 			base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2263 		}
2264 
CheckBase()2265 		protected override bool CheckBase ()
2266 		{
2267 			if ((caching_flags & Flags.MethodOverloadsExist) != 0)
2268 				CheckForDuplications ();
2269 
2270 			// Don't check base, destructors have special syntax
2271 			return true;
2272 		}
2273 
Define()2274 		public override bool Define ()
2275 		{
2276 			base.Define ();
2277 
2278 			if (Compiler.Settings.WriteMetadataOnly)
2279 				block = null;
2280 
2281 			return true;
2282 		}
2283 
Emit()2284 		public override void Emit()
2285 		{
2286 			var base_type = Parent.PartialContainer.BaseType;
2287 			if (base_type != null && Block != null) {
2288 				var base_dtor = MemberCache.FindMember (base_type,
2289 					new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
2290 
2291 				if (base_dtor == null)
2292 					throw new NotImplementedException ();
2293 
2294 				MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
2295 				method_expr.InstanceExpression = new BaseThis (base_type, Location);
2296 
2297 				var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation) {
2298 					IsCompilerGenerated = true
2299 				};
2300 				var finaly_block = new ExplicitBlock (block, Location, Location) {
2301 					IsCompilerGenerated = true
2302 				};
2303 
2304 				//
2305 				// 0-size arguments to avoid CS0250 error
2306 				// TODO: Should use AddScopeStatement or something else which emits correct
2307 				// debugger scope
2308 				//
2309 				finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)), Location.Null));
2310 
2311 				var tf = new TryFinally (try_block, finaly_block, Location);
2312 				block.WrapIntoDestructor (tf, try_block);
2313 			}
2314 
2315 			base.Emit ();
2316 		}
2317 
GetSignatureForError()2318 		public override string GetSignatureForError ()
2319 		{
2320 			return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
2321 		}
2322 
ResolveMemberType()2323 		protected override bool ResolveMemberType ()
2324 		{
2325 			member_type = Compiler.BuiltinTypes.Void;
2326 			return true;
2327 		}
2328 
2329 		public override string[] ValidAttributeTargets {
2330 			get {
2331 				return attribute_targets;
2332 			}
2333 		}
2334 	}
2335 
2336 	// Ooouh Martin, templates are missing here.
2337 	// When it will be possible move here a lot of child code and template method type.
2338 	public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData, IMethodDefinition {
2339 		protected MethodData method_data;
2340 		protected ToplevelBlock block;
2341 		protected SecurityType declarative_security;
2342 
2343 		protected readonly string prefix;
2344 
2345 		ReturnParameter return_attributes;
2346 
AbstractPropertyEventMethod(InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)2347 		protected AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
2348 			: base (member.Parent, SetupName (prefix, member, loc), attrs)
2349 		{
2350 			this.prefix = prefix;
2351 		}
2352 
SetupName(string prefix, InterfaceMemberBase member, Location loc)2353 		static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2354 		{
2355 			return new MemberName (member.MemberName.Left, prefix + member.ShortName, member.MemberName.ExplicitInterface, loc);
2356 		}
2357 
UpdateName(InterfaceMemberBase member)2358 		public void UpdateName (InterfaceMemberBase member)
2359 		{
2360 			SetMemberName (SetupName (prefix, member, Location));
2361 		}
2362 
2363 		#region IMethodData Members
2364 
2365 		public ToplevelBlock Block {
2366 			get {
2367 				return block;
2368 			}
2369 
2370 			set {
2371 				block = value;
2372 			}
2373 		}
2374 
2375 		public CallingConventions CallingConventions {
2376 			get {
2377 				return CallingConventions.Standard;
2378 			}
2379 		}
2380 
CreateEmitContext(ILGenerator ig, SourceMethodBuilder sourceMethod)2381 		public EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
2382 		{
2383 			return new EmitContext (this, ig, ReturnType, sourceMethod);
2384 		}
2385 
2386 		public bool IsAccessor {
2387 			get {
2388 				return true;
2389 			}
2390 		}
2391 
2392 		public MemberName MethodName {
2393 			get {
2394 				return MemberName;
2395 			}
2396 		}
2397 
2398 		public TypeSpec[] ParameterTypes {
2399 			get {
2400 				return ParameterInfo.Types;
2401 			}
2402 		}
2403 
2404 		MethodBase IMethodDefinition.Metadata {
2405 			get {
2406 				return method_data.MethodBuilder;
2407 			}
2408 		}
2409 
2410 		public abstract ParametersCompiled ParameterInfo { get ; }
2411 		public abstract TypeSpec ReturnType { get; }
2412 
2413 		#endregion
2414 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)2415 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2416 		{
2417 			if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2418 				Report.Error (1667, a.Location,
2419 					"Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2420 					a.Type.GetSignatureForError (), a.GetValidTargets ());
2421 				return;
2422 			}
2423 
2424 			if (a.IsValidSecurityAttribute ()) {
2425 				a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2426 				return;
2427 			}
2428 
2429 			if (a.Target == AttributeTargets.Method) {
2430 				method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2431 				return;
2432 			}
2433 
2434 			if (a.Target == AttributeTargets.ReturnValue) {
2435 				CreateReturnBuilder ();
2436 				return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2437 				return;
2438 			}
2439 
2440 			ApplyToExtraTarget (a, ctor, cdata, pa);
2441 		}
2442 
ApplyToExtraTarget(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)2443 		protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2444 		{
2445 			throw new NotSupportedException ("You forgot to define special attribute target handling");
2446 		}
2447 
2448 		// It is not supported for the accessors
Define()2449 		public sealed override bool Define()
2450 		{
2451 			throw new NotSupportedException ();
2452 		}
2453 
CreateReturnBuilder()2454 		ReturnParameter CreateReturnBuilder ()
2455 		{
2456 			return return_attributes ?? (return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location));
2457 		}
2458 
Emit(TypeDefinition parent)2459 		public virtual void Emit (TypeDefinition parent)
2460 		{
2461 			method_data.Emit (parent);
2462 
2463 			if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2464 				Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2465 			if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2466 				Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2467 
2468 			if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2469 				Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder);
2470 			} else if (ReturnType.HasDynamicElement) {
2471 				Module.PredefinedAttributes.Dynamic.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
2472 			} else if (ReturnType is ReadOnlyReferenceContainer) {
2473 				Module.PredefinedAttributes.IsReadOnly.EmitAttribute (CreateReturnBuilder ().Builder);
2474 			}
2475 
2476 			if (ReturnType.HasNamedTupleElement) {
2477 				Module.PredefinedAttributes.TupleElementNames.EmitAttribute (CreateReturnBuilder ().Builder, ReturnType, Location);
2478 			}
2479 
2480 			if (OptAttributes != null)
2481 				OptAttributes.Emit ();
2482 
2483 			if (declarative_security != null) {
2484 				foreach (var de in declarative_security) {
2485 #if STATIC
2486 					method_data.MethodBuilder.__AddDeclarativeSecurity (de);
2487 #else
2488 					method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2489 #endif
2490 				}
2491 			}
2492 
2493 			block = null;
2494 		}
2495 
EnableOverloadChecks(MemberCore overload)2496 		public override bool EnableOverloadChecks (MemberCore overload)
2497 		{
2498 			if (overload is MethodCore) {
2499 				caching_flags |= Flags.MethodOverloadsExist;
2500 				return true;
2501 			}
2502 
2503 			// This can only happen with indexers and it will
2504 			// be catched as indexer difference
2505 			if (overload is AbstractPropertyEventMethod)
2506 				return true;
2507 
2508 			return false;
2509 		}
2510 
GetCallerMemberName()2511 		public override string GetCallerMemberName ()
2512 		{
2513 			return base.GetCallerMemberName ().Substring (prefix.Length);
2514 		}
2515 
GetSignatureForDocumentation()2516 		public override string GetSignatureForDocumentation ()
2517 		{
2518 			// should not be called
2519 			throw new NotSupportedException ();
2520 		}
2521 
IsClsComplianceRequired()2522 		public override bool IsClsComplianceRequired()
2523 		{
2524 			return false;
2525 		}
2526 
PrepareEmit()2527 		public void PrepareEmit ()
2528 		{
2529 			method_data.DefineMethodBuilder (Parent.PartialContainer, ParameterInfo);
2530 		}
2531 
WriteDebugSymbol(MonoSymbolFile file)2532 		public override void WriteDebugSymbol (MonoSymbolFile file)
2533 		{
2534 			if (method_data != null)
2535 				method_data.WriteDebugSymbol (file);
2536 		}
2537 
2538 		public MethodSpec Spec { get; protected set; }
2539 
2540 		//
2541 		//   Represents header string for documentation comment.
2542 		//
2543 		public override string DocCommentHeader {
2544 			get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2545 		}
2546 	}
2547 
2548 	public class Operator : MethodOrOperator {
2549 
2550 		const Modifiers AllowedModifiers =
2551 			Modifiers.PUBLIC |
2552 			Modifiers.UNSAFE |
2553 			Modifiers.EXTERN |
2554 			Modifiers.STATIC;
2555 
2556 		public enum OpType : byte {
2557 
2558 			// Unary operators
2559 			LogicalNot,
2560 			OnesComplement,
2561 			Increment,
2562 			Decrement,
2563 			True,
2564 			False,
2565 
2566 			// Unary and Binary operators
2567 			Addition,
2568 			Subtraction,
2569 
2570 			UnaryPlus,
2571 			UnaryNegation,
2572 
2573 			// Binary operators
2574 			Multiply,
2575 			Division,
2576 			Modulus,
2577 			BitwiseAnd,
2578 			BitwiseOr,
2579 			ExclusiveOr,
2580 			LeftShift,
2581 			RightShift,
2582 			Equality,
2583 			Inequality,
2584 			GreaterThan,
2585 			LessThan,
2586 			GreaterThanOrEqual,
2587 			LessThanOrEqual,
2588 
2589 			// Implicit and Explicit
2590 			Implicit,
2591 			Explicit,
2592 
2593 			// Pattern matching
2594 			Is,
2595 
2596 			// Just because of enum
2597 			TOP
2598 		};
2599 
2600 		public readonly OpType OperatorType;
2601 
2602 		static readonly string [] [] names;
2603 
Operator()2604 		static Operator ()
2605 		{
2606 			names = new string[(int)OpType.TOP][];
2607 			names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2608 			names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2609 			names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2610 			names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2611 			names [(int) OpType.True] = new string [] { "true", "op_True" };
2612 			names [(int) OpType.False] = new string [] { "false", "op_False" };
2613 			names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2614 			names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2615 			names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2616 			names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2617 			names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2618 			names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2619 			names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2620 			names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2621 			names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2622 			names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2623 			names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2624 			names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2625 			names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2626 			names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2627 			names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2628 			names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2629 			names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2630 			names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2631 			names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2632 			names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2633 			names [(int) OpType.Is] = new string[] { "is", "op_Is" };
2634 		}
2635 
Operator(TypeDefinition parent, OpType type, FullNamedExpression ret_type, Modifiers mod_flags, ParametersCompiled parameters, ToplevelBlock block, Attributes attrs, Location loc)2636 		public Operator (TypeDefinition parent, OpType type, FullNamedExpression ret_type, Modifiers mod_flags, ParametersCompiled parameters,
2637 				 ToplevelBlock block, Attributes attrs, Location loc)
2638 			: base (parent, ret_type, mod_flags, AllowedModifiers, new MemberName (GetMetadataName (type), loc), attrs, parameters)
2639 		{
2640 			OperatorType = type;
2641 			Block = block;
2642 		}
2643 
Accept(StructuralVisitor visitor)2644 		public override void Accept (StructuralVisitor visitor)
2645 		{
2646 			visitor.Visit (this);
2647 		}
2648 
ApplyAttributeBuilder(Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)2649 		public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2650 		{
2651 			if (a.Type == pa.Conditional) {
2652 				Error_ConditionalAttributeIsNotValid ();
2653 				return;
2654 			}
2655 
2656 			base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2657 		}
2658 
Define()2659 		public override bool Define ()
2660 		{
2661 			const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2662 			if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2663 				Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2664 			}
2665 
2666 			if (!base.Define ())
2667 				return false;
2668 
2669 			if (block != null) {
2670 				if (block.IsIterator) {
2671 					//
2672 					// Current method is turned into automatically generated
2673 					// wrapper which creates an instance of iterator
2674 					//
2675 					Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
2676 					ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2677 				}
2678 
2679 				if (Compiler.Settings.WriteMetadataOnly)
2680 					block = null;
2681 			}
2682 
2683 			// imlicit and explicit operator of same types are not allowed
2684 			if (OperatorType == OpType.Explicit)
2685 				Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2686 			else if (OperatorType == OpType.Implicit)
2687 				Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2688 
2689 			TypeSpec declaring_type = Parent.PartialContainer.CurrentType;
2690 			TypeSpec return_type = MemberType;
2691 			TypeSpec first_arg_type = ParameterTypes [0];
2692 
2693 			TypeSpec first_arg_type_unwrap = first_arg_type;
2694 			if (first_arg_type.IsNullableType)
2695 				first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type);
2696 
2697 			TypeSpec return_type_unwrap = return_type;
2698 			if (return_type.IsNullableType)
2699 				return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type);
2700 
2701 			//
2702 			// Rules for conversion operators
2703 			//
2704 			if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2705 				if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
2706 					Report.Error (555, Location,
2707 						"User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2708 					return false;
2709 				}
2710 
2711 				TypeSpec conv_type;
2712 				if (declaring_type == return_type || declaring_type == return_type_unwrap) {
2713 					conv_type = first_arg_type;
2714 				} else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) {
2715 					conv_type = return_type;
2716 				} else {
2717 					Report.Error (556, Location,
2718 						"User-defined conversion must convert to or from the enclosing type");
2719 					return false;
2720 				}
2721 
2722 				if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2723 					Report.Error (1964, Location,
2724 						"User-defined conversion `{0}' cannot convert to or from the dynamic type",
2725 						GetSignatureForError ());
2726 
2727 					return false;
2728 				}
2729 
2730 				if (conv_type.IsInterface) {
2731 					Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2732 						GetSignatureForError ());
2733 					return false;
2734 				}
2735 
2736 				if (conv_type.IsClass) {
2737 					if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) {
2738 						Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2739 							GetSignatureForError ());
2740 						return false;
2741 					}
2742 
2743 					if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) {
2744 						Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2745 							GetSignatureForError ());
2746 						return false;
2747 					}
2748 				}
2749 			} else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2750 				if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) {
2751 					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");
2752 					return false;
2753 				}
2754 			} else if (parameters.Count == 1) {
2755 				// Checks for Unary operators
2756 
2757 				if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2758 					if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) {
2759 						Report.Error (448, Location,
2760 							"The return type for ++ or -- operator must be the containing type or derived from the containing type");
2761 						return false;
2762 					}
2763 					if (first_arg_type != declaring_type) {
2764 						Report.Error (
2765 							559, Location, "The parameter type for ++ or -- operator must be the containing type");
2766 						return false;
2767 					}
2768 				}
2769 
2770 				if (first_arg_type_unwrap != declaring_type) {
2771 					Report.Error (562, Location,
2772 						"The parameter type of a unary operator must be the containing type");
2773 					return false;
2774 				}
2775 
2776 				if (OperatorType == OpType.True || OperatorType == OpType.False) {
2777 					if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) {
2778 						Report.Error (
2779 							215, Location,
2780 							"The return type of operator True or False " +
2781 							"must be bool");
2782 						return false;
2783 					}
2784 				}
2785 
2786 			} else if (first_arg_type_unwrap != declaring_type) {
2787 				// Checks for Binary operators
2788 
2789 				var second_arg_type = ParameterTypes[1];
2790 				if (second_arg_type.IsNullableType)
2791 					second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type);
2792 
2793 				if (second_arg_type != declaring_type) {
2794 					Report.Error (563, Location,
2795 						"One of the parameters of a binary operator must be the containing type");
2796 					return false;
2797 				}
2798 			}
2799 
2800 			return true;
2801 		}
2802 
ResolveMemberType()2803 		protected override bool ResolveMemberType ()
2804 		{
2805 			if (!base.ResolveMemberType ())
2806 				return false;
2807 
2808 			flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2809 			return true;
2810 		}
2811 
FindBaseMember(out MemberSpec bestCandidate, ref bool overrides)2812 		protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
2813 		{
2814 			// Operator cannot be override
2815 			bestCandidate = null;
2816 			return null;
2817 		}
2818 
GetName(OpType ot)2819 		public static string GetName (OpType ot)
2820 		{
2821 			return names [(int) ot] [0];
2822 		}
2823 
GetName(string metadata_name)2824 		public static string GetName (string metadata_name)
2825 		{
2826 			for (int i = 0; i < names.Length; ++i) {
2827 				if (names [i] [1] == metadata_name)
2828 					return names [i] [0];
2829 			}
2830 			return null;
2831 		}
2832 
GetMetadataName(OpType ot)2833 		public static string GetMetadataName (OpType ot)
2834 		{
2835 			return names [(int) ot] [1];
2836 		}
2837 
GetMetadataName(string name)2838 		public static string GetMetadataName (string name)
2839 		{
2840 			for (int i = 0; i < names.Length; ++i) {
2841 				if (names [i] [0] == name)
2842 					return names [i] [1];
2843 			}
2844 			return null;
2845 		}
2846 
GetType(string metadata_name)2847 		public static OpType? GetType (string metadata_name)
2848 		{
2849 			for (int i = 0; i < names.Length; ++i) {
2850 				if (names[i][1] == metadata_name)
2851 					return (OpType) i;
2852 			}
2853 
2854 			return null;
2855 		}
2856 
GetMatchingOperator()2857 		public OpType GetMatchingOperator ()
2858 		{
2859 			switch (OperatorType) {
2860 			case OpType.Equality:
2861 				return OpType.Inequality;
2862 			case OpType.Inequality:
2863 				return OpType.Equality;
2864 			case OpType.True:
2865 				return OpType.False;
2866 			case OpType.False:
2867 				return OpType.True;
2868 			case OpType.GreaterThan:
2869 				return OpType.LessThan;
2870 			case OpType.LessThan:
2871 				return OpType.GreaterThan;
2872 			case OpType.GreaterThanOrEqual:
2873 				return OpType.LessThanOrEqual;
2874 			case OpType.LessThanOrEqual:
2875 				return OpType.GreaterThanOrEqual;
2876 			default:
2877 				return OpType.TOP;
2878 			}
2879 		}
2880 
GetSignatureForDocumentation()2881 		public override string GetSignatureForDocumentation ()
2882 		{
2883 			string s = base.GetSignatureForDocumentation ();
2884 			if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2885 				s = s + "~" + ReturnType.GetSignatureForDocumentation ();
2886 			}
2887 
2888 			return s;
2889 		}
2890 
GetSignatureForError()2891 		public override string GetSignatureForError ()
2892 		{
2893 			StringBuilder sb = new StringBuilder ();
2894 			if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2895 				sb.AppendFormat ("{0}.{1} operator {2}",
2896 					Parent.GetSignatureForError (), GetName (OperatorType),
2897 					member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ());
2898 			}
2899 			else {
2900 				sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2901 			}
2902 
2903 			sb.Append (parameters.GetSignatureForError ());
2904 			return sb.ToString ();
2905 		}
2906 	}
2907 }
2908 
2909