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