/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs

http://github.com/icsharpcode/ILSpy · C# · 2890 lines · 2169 code · 503 blank · 218 comment · 694 complexity · 65ab7f80bbae0fbfd7bf92a03d76434a MD5 · raw file

Large files are truncated click here to view the full file

  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. using System;
  15. using System.Collections.Generic;
  16. using System.Security;
  17. using System.Security.Permissions;
  18. using System.Text;
  19. using System.Linq;
  20. using Mono.CompilerServices.SymbolWriter;
  21. using System.Runtime.CompilerServices;
  22. #if NET_2_1
  23. using XmlElement = System.Object;
  24. #else
  25. using System.Xml;
  26. #endif
  27. #if STATIC
  28. using MetaType = IKVM.Reflection.Type;
  29. using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
  30. using IKVM.Reflection;
  31. using IKVM.Reflection.Emit;
  32. #else
  33. using MetaType = System.Type;
  34. using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
  35. using System.Reflection;
  36. using System.Reflection.Emit;
  37. #endif
  38. namespace Mono.CSharp {
  39. public abstract class MethodCore : InterfaceMemberBase, IParametersMember
  40. {
  41. protected ParametersCompiled parameters;
  42. protected ToplevelBlock block;
  43. protected MethodSpec spec;
  44. protected MethodCore (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
  45. MemberName name, Attributes attrs, ParametersCompiled parameters)
  46. : base (parent, type, mod, allowed_mod, name, attrs)
  47. {
  48. this.parameters = parameters;
  49. }
  50. public override Variance ExpectedMemberTypeVariance {
  51. get {
  52. return Variance.Covariant;
  53. }
  54. }
  55. //
  56. // Returns the System.Type array for the parameters of this method
  57. //
  58. public TypeSpec [] ParameterTypes {
  59. get {
  60. return parameters.Types;
  61. }
  62. }
  63. public ParametersCompiled ParameterInfo {
  64. get {
  65. return parameters;
  66. }
  67. }
  68. AParametersCollection IParametersMember.Parameters {
  69. get { return parameters; }
  70. }
  71. public ToplevelBlock Block {
  72. get {
  73. return block;
  74. }
  75. set {
  76. block = value;
  77. }
  78. }
  79. public CallingConventions CallingConventions {
  80. get {
  81. CallingConventions cc = parameters.CallingConvention;
  82. if (!IsInterface)
  83. if ((ModFlags & Modifiers.STATIC) == 0)
  84. cc |= CallingConventions.HasThis;
  85. // FIXME: How is `ExplicitThis' used in C#?
  86. return cc;
  87. }
  88. }
  89. protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
  90. {
  91. bool res = base.CheckOverrideAgainstBase (base_member);
  92. //
  93. // Check that the permissions are not being changed
  94. //
  95. if (!CheckAccessModifiers (this, base_member)) {
  96. Error_CannotChangeAccessModifiers (this, base_member);
  97. res = false;
  98. }
  99. return res;
  100. }
  101. protected override bool CheckBase ()
  102. {
  103. // Check whether arguments were correct.
  104. if (!DefineParameters (parameters))
  105. return false;
  106. return base.CheckBase ();
  107. }
  108. //
  109. // Represents header string for documentation comment.
  110. //
  111. public override string DocCommentHeader
  112. {
  113. get { return "M:"; }
  114. }
  115. public override void Emit ()
  116. {
  117. if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
  118. parameters.CheckConstraints (this);
  119. }
  120. base.Emit ();
  121. }
  122. public override bool EnableOverloadChecks (MemberCore overload)
  123. {
  124. if (overload is MethodCore) {
  125. caching_flags |= Flags.MethodOverloadsExist;
  126. return true;
  127. }
  128. if (overload is AbstractPropertyEventMethod)
  129. return true;
  130. return base.EnableOverloadChecks (overload);
  131. }
  132. public override string GetSignatureForDocumentation ()
  133. {
  134. string s = base.GetSignatureForDocumentation ();
  135. if (MemberName.Arity > 0)
  136. s += "``" + MemberName.Arity.ToString ();
  137. return s + parameters.GetSignatureForDocumentation ();
  138. }
  139. public MethodSpec Spec {
  140. get { return spec; }
  141. }
  142. protected override bool VerifyClsCompliance ()
  143. {
  144. if (!base.VerifyClsCompliance ())
  145. return false;
  146. if (parameters.HasArglist) {
  147. Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
  148. }
  149. if (member_type != null && !member_type.IsCLSCompliant ()) {
  150. Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
  151. GetSignatureForError ());
  152. }
  153. parameters.VerifyClsCompliance (this);
  154. return true;
  155. }
  156. }
  157. public interface IGenericMethodDefinition : IMethodDefinition
  158. {
  159. TypeParameterSpec[] TypeParameters { get; }
  160. int TypeParametersCount { get; }
  161. // MethodInfo MakeGenericMethod (TypeSpec[] targs);
  162. }
  163. public sealed class MethodSpec : MemberSpec, IParametersMember
  164. {
  165. MethodBase inflatedMetaInfo;
  166. AParametersCollection parameters;
  167. TypeSpec returnType;
  168. TypeSpec[] targs;
  169. TypeParameterSpec[] constraints;
  170. public static readonly MethodSpec Excluded = new MethodSpec (MemberKind.Method, InternalType.FakeInternalType, null, null, ParametersCompiled.EmptyReadOnlyParameters, 0);
  171. public MethodSpec (MemberKind kind, TypeSpec declaringType, IMethodDefinition details, TypeSpec returnType,
  172. AParametersCollection parameters, Modifiers modifiers)
  173. : base (kind, declaringType, details, modifiers)
  174. {
  175. this.parameters = parameters;
  176. this.returnType = returnType;
  177. }
  178. #region Properties
  179. public override int Arity {
  180. get {
  181. return IsGeneric ? GenericDefinition.TypeParametersCount : 0;
  182. }
  183. }
  184. public TypeParameterSpec[] Constraints {
  185. get {
  186. if (constraints == null && IsGeneric)
  187. constraints = GenericDefinition.TypeParameters;
  188. return constraints;
  189. }
  190. }
  191. public bool IsConstructor {
  192. get {
  193. return Kind == MemberKind.Constructor;
  194. }
  195. }
  196. public new IMethodDefinition MemberDefinition {
  197. get {
  198. return (IMethodDefinition) definition;
  199. }
  200. }
  201. public IGenericMethodDefinition GenericDefinition {
  202. get {
  203. return (IGenericMethodDefinition) definition;
  204. }
  205. }
  206. public bool IsAsync {
  207. get {
  208. return (Modifiers & Modifiers.ASYNC) != 0;
  209. }
  210. }
  211. public bool IsExtensionMethod {
  212. get {
  213. return IsStatic && parameters.HasExtensionMethodType;
  214. }
  215. }
  216. public bool IsSealed {
  217. get {
  218. return (Modifiers & Modifiers.SEALED) != 0;
  219. }
  220. }
  221. // When is virtual or abstract
  222. public bool IsVirtual {
  223. get {
  224. return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
  225. }
  226. }
  227. public bool IsReservedMethod {
  228. get {
  229. return Kind == MemberKind.Operator || IsAccessor;
  230. }
  231. }
  232. TypeSpec IInterfaceMemberSpec.MemberType {
  233. get {
  234. return returnType;
  235. }
  236. }
  237. public AParametersCollection Parameters {
  238. get {
  239. return parameters;
  240. }
  241. }
  242. public TypeSpec ReturnType {
  243. get {
  244. return returnType;
  245. }
  246. }
  247. public TypeSpec[] TypeArguments {
  248. get {
  249. return targs;
  250. }
  251. }
  252. #endregion
  253. public MethodSpec GetGenericMethodDefinition ()
  254. {
  255. if (!IsGeneric && !DeclaringType.IsGeneric)
  256. return this;
  257. return MemberCache.GetMember (declaringType, this);
  258. }
  259. public MethodBase GetMetaInfo ()
  260. {
  261. //
  262. // inflatedMetaInfo is extra field needed for cases where we
  263. // inflate method but another nested type can later inflate
  264. // again (the cache would be build with inflated metaInfo) and
  265. // TypeBuilder can work with method definitions only
  266. //
  267. if (inflatedMetaInfo == null) {
  268. if ((state & StateFlags.PendingMetaInflate) != 0) {
  269. var dt_meta = DeclaringType.GetMetaInfo ();
  270. if (DeclaringType.IsTypeBuilder) {
  271. if (IsConstructor)
  272. inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) MemberDefinition.Metadata);
  273. else
  274. inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) MemberDefinition.Metadata);
  275. } else {
  276. #if STATIC
  277. // it should not be reached
  278. throw new NotImplementedException ();
  279. #else
  280. inflatedMetaInfo = MethodInfo.GetMethodFromHandle (MemberDefinition.Metadata.MethodHandle, dt_meta.TypeHandle);
  281. #endif
  282. }
  283. state &= ~StateFlags.PendingMetaInflate;
  284. } else {
  285. inflatedMetaInfo = MemberDefinition.Metadata;
  286. }
  287. }
  288. if ((state & StateFlags.PendingMakeMethod) != 0) {
  289. var sre_targs = new MetaType[targs.Length];
  290. for (int i = 0; i < sre_targs.Length; ++i)
  291. sre_targs[i] = targs[i].GetMetaInfo ();
  292. inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs);
  293. state &= ~StateFlags.PendingMakeMethod;
  294. }
  295. return inflatedMetaInfo;
  296. }
  297. public override string GetSignatureForDocumentation ()
  298. {
  299. string name;
  300. switch (Kind) {
  301. case MemberKind.Constructor:
  302. name = "#ctor";
  303. break;
  304. case MemberKind.Method:
  305. if (Arity > 0)
  306. name = Name + "``" + Arity.ToString ();
  307. else
  308. name = Name;
  309. break;
  310. default:
  311. name = Name;
  312. break;
  313. }
  314. name = DeclaringType.GetSignatureForDocumentation () + "." + name + parameters.GetSignatureForDocumentation ();
  315. if (Kind == MemberKind.Operator) {
  316. var op = Operator.GetType (Name).Value;
  317. if (op == Operator.OpType.Explicit || op == Operator.OpType.Implicit) {
  318. name += "~" + ReturnType.GetSignatureForDocumentation ();
  319. }
  320. }
  321. return name;
  322. }
  323. public override string GetSignatureForError ()
  324. {
  325. string name;
  326. if (IsConstructor) {
  327. name = DeclaringType.GetSignatureForError () + "." + DeclaringType.Name;
  328. } else if (Kind == MemberKind.Operator) {
  329. var op = Operator.GetType (Name).Value;
  330. if (op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) {
  331. name = DeclaringType.GetSignatureForError () + "." + Operator.GetName (op) + " operator " + returnType.GetSignatureForError ();
  332. } else {
  333. name = DeclaringType.GetSignatureForError () + ".operator " + Operator.GetName (op);
  334. }
  335. } else if (IsAccessor) {
  336. int split = Name.IndexOf ('_');
  337. name = Name.Substring (split + 1);
  338. var postfix = Name.Substring (0, split);
  339. if (split == 3) {
  340. var pc = parameters.Count;
  341. if (pc > 0 && postfix == "get") {
  342. name = "this" + parameters.GetSignatureForError ("[", "]", pc);
  343. } else if (pc > 1 && postfix == "set") {
  344. name = "this" + parameters.GetSignatureForError ("[", "]", pc - 1);
  345. }
  346. }
  347. return DeclaringType.GetSignatureForError () + "." + name + "." + postfix;
  348. } else {
  349. name = base.GetSignatureForError ();
  350. if (targs != null)
  351. name += "<" + TypeManager.CSharpName (targs) + ">";
  352. else if (IsGeneric)
  353. name += "<" + TypeManager.CSharpName (GenericDefinition.TypeParameters) + ">";
  354. }
  355. return name + parameters.GetSignatureForError ();
  356. }
  357. public override MemberSpec InflateMember (TypeParameterInflator inflator)
  358. {
  359. var ms = (MethodSpec) base.InflateMember (inflator);
  360. ms.inflatedMetaInfo = null;
  361. ms.returnType = inflator.Inflate (returnType);
  362. ms.parameters = parameters.Inflate (inflator);
  363. if (IsGeneric)
  364. ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints);
  365. return ms;
  366. }
  367. public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs)
  368. {
  369. if (targs == null)
  370. throw new ArgumentNullException ();
  371. // TODO MemberCache
  372. // if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance))
  373. // return ginstance;
  374. //if (generic_intances == null)
  375. // generic_intances = new Dictionary<TypeSpec[], Method> (TypeSpecArrayComparer.Default);
  376. var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs);
  377. var inflated = (MethodSpec) MemberwiseClone ();
  378. inflated.declaringType = inflator.TypeInstance;
  379. inflated.returnType = inflator.Inflate (returnType);
  380. inflated.parameters = parameters.Inflate (inflator);
  381. inflated.targs = targs;
  382. inflated.constraints = TypeParameterSpec.InflateConstraints (inflator, constraints ?? GenericDefinition.TypeParameters);
  383. inflated.state |= StateFlags.PendingMakeMethod;
  384. // if (inflated.parent == null)
  385. // inflated.parent = parent;
  386. //generic_intances.Add (targs, inflated);
  387. return inflated;
  388. }
  389. public MethodSpec Mutate (TypeParameterMutator mutator)
  390. {
  391. var targs = TypeArguments;
  392. if (targs != null)
  393. targs = mutator.Mutate (targs);
  394. var decl = DeclaringType;
  395. if (DeclaringType.IsGenericOrParentIsGeneric) {
  396. decl = mutator.Mutate (decl);
  397. }
  398. if (targs == TypeArguments && decl == DeclaringType)
  399. return this;
  400. var ms = (MethodSpec) MemberwiseClone ();
  401. if (decl != DeclaringType) {
  402. ms.inflatedMetaInfo = null;
  403. ms.declaringType = decl;
  404. ms.state |= StateFlags.PendingMetaInflate;
  405. }
  406. if (targs != null) {
  407. ms.targs = targs;
  408. ms.state |= StateFlags.PendingMakeMethod;
  409. }
  410. return ms;
  411. }
  412. public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
  413. {
  414. var missing = returnType.ResolveMissingDependencies (this);
  415. foreach (var pt in parameters.Types) {
  416. var m = pt.GetMissingDependencies (this);
  417. if (m == null)
  418. continue;
  419. if (missing == null)
  420. missing = new List<MissingTypeSpecReference> ();
  421. missing.AddRange (m);
  422. }
  423. if (Arity > 0) {
  424. foreach (var tp in GenericDefinition.TypeParameters) {
  425. var m = tp.GetMissingDependencies (this);
  426. if (m == null)
  427. continue;
  428. if (missing == null)
  429. missing = new List<MissingTypeSpecReference> ();
  430. missing.AddRange (m);
  431. }
  432. }
  433. return missing;
  434. }
  435. }
  436. public abstract class MethodOrOperator : MethodCore, IMethodData, IMethodDefinition
  437. {
  438. ReturnParameter return_attributes;
  439. SecurityType declarative_security;
  440. protected MethodData MethodData;
  441. static readonly string[] attribute_targets = new string [] { "method", "return" };
  442. protected MethodOrOperator (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name,
  443. Attributes attrs, ParametersCompiled parameters)
  444. : base (parent, type, mod, allowed_mod, name, attrs, parameters)
  445. {
  446. }
  447. public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  448. {
  449. if (a.Target == AttributeTargets.ReturnValue) {
  450. if (return_attributes == null)
  451. return_attributes = new ReturnParameter (this, MethodBuilder, Location);
  452. return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
  453. return;
  454. }
  455. if (a.Type == pa.MethodImpl) {
  456. if ((ModFlags & Modifiers.ASYNC) != 0 && (a.GetMethodImplOptions () & MethodImplOptions.Synchronized) != 0) {
  457. Report.Error (4015, a.Location, "`{0}': Async methods cannot use `MethodImplOptions.Synchronized'",
  458. GetSignatureForError ());
  459. }
  460. is_external_implementation = a.IsInternalCall ();
  461. } else if (a.Type == pa.DllImport) {
  462. const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
  463. if ((ModFlags & extern_static) != extern_static) {
  464. Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
  465. }
  466. if (MemberName.IsGeneric || Parent.IsGenericOrParentIsGeneric) {
  467. Report.Error (7042, a.Location,
  468. "The DllImport attribute cannot be applied to a method that is generic or contained in a generic type");
  469. }
  470. is_external_implementation = true;
  471. }
  472. if (a.IsValidSecurityAttribute ()) {
  473. a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
  474. return;
  475. }
  476. if (MethodBuilder != null)
  477. MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
  478. }
  479. public override AttributeTargets AttributeTargets {
  480. get {
  481. return AttributeTargets.Method;
  482. }
  483. }
  484. MethodBase IMethodDefinition.Metadata {
  485. get {
  486. return MethodData.MethodBuilder;
  487. }
  488. }
  489. // TODO: Remove and use MethodData abstraction
  490. public MethodBuilder MethodBuilder {
  491. get {
  492. return MethodData.MethodBuilder;
  493. }
  494. }
  495. protected override bool CheckForDuplications ()
  496. {
  497. return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
  498. }
  499. public virtual EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
  500. {
  501. return new EmitContext (this, ig, MemberType, sourceMethod);
  502. }
  503. public override bool Define ()
  504. {
  505. if (!base.Define ())
  506. return false;
  507. if (!CheckBase ())
  508. return false;
  509. MemberKind kind;
  510. if (this is Operator)
  511. kind = MemberKind.Operator;
  512. else if (this is Destructor)
  513. kind = MemberKind.Destructor;
  514. else
  515. kind = MemberKind.Method;
  516. string explicit_name;
  517. if (IsPartialDefinition) {
  518. caching_flags &= ~Flags.Excluded_Undetected;
  519. caching_flags |= Flags.Excluded;
  520. // Add to member cache only when a partial method implementation has not been found yet
  521. if ((caching_flags & Flags.PartialDefinitionExists) != 0)
  522. return true;
  523. if (IsExplicitImpl)
  524. return true;
  525. explicit_name = null;
  526. } else {
  527. MethodData = new MethodData (this, ModFlags, flags, this, base_method);
  528. if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName)))
  529. return false;
  530. explicit_name = MethodData.MetadataName;
  531. }
  532. spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, parameters, ModFlags);
  533. if (MemberName.Arity > 0)
  534. spec.IsGeneric = true;
  535. Parent.MemberCache.AddMember (this, explicit_name, spec);
  536. return true;
  537. }
  538. protected override void DoMemberTypeIndependentChecks ()
  539. {
  540. base.DoMemberTypeIndependentChecks ();
  541. CheckAbstractAndExtern (block != null);
  542. if ((ModFlags & Modifiers.PARTIAL) != 0) {
  543. for (int i = 0; i < parameters.Count; ++i) {
  544. IParameterData p = parameters.FixedParameters [i];
  545. if ((p.ModFlags & Parameter.Modifier.OUT) != 0) {
  546. Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
  547. GetSignatureForError ());
  548. }
  549. if (p.HasDefaultValue && IsPartialImplementation)
  550. ((Parameter) p).Warning_UselessOptionalParameter (Report);
  551. }
  552. }
  553. }
  554. protected override void DoMemberTypeDependentChecks ()
  555. {
  556. base.DoMemberTypeDependentChecks ();
  557. if (MemberType.IsStatic) {
  558. Error_StaticReturnType ();
  559. }
  560. }
  561. public override void Emit ()
  562. {
  563. if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
  564. Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder);
  565. if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
  566. Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder);
  567. if ((ModFlags & Modifiers.DEBUGGER_STEP_THROUGH) != 0)
  568. Module.PredefinedAttributes.DebuggerStepThrough.EmitAttribute (MethodBuilder);
  569. if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  570. return_attributes = new ReturnParameter (this, MethodBuilder, Location);
  571. Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
  572. } else if (ReturnType.HasDynamicElement) {
  573. return_attributes = new ReturnParameter (this, MethodBuilder, Location);
  574. Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
  575. }
  576. if (OptAttributes != null)
  577. OptAttributes.Emit ();
  578. if (declarative_security != null) {
  579. foreach (var de in declarative_security) {
  580. #if STATIC
  581. MethodBuilder.__AddDeclarativeSecurity (de);
  582. #else
  583. MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
  584. #endif
  585. }
  586. }
  587. if (type_expr != null)
  588. ConstraintChecker.Check (this, member_type, type_expr.Location);
  589. base.Emit ();
  590. if (MethodData != null)
  591. MethodData.Emit (Parent);
  592. if (block != null && block.StateMachine is AsyncTaskStorey) {
  593. var psm = Module.PredefinedAttributes.AsyncStateMachine;
  594. psm.EmitAttribute (MethodBuilder, block.StateMachine);
  595. }
  596. if ((ModFlags & Modifiers.PARTIAL) == 0)
  597. Block = null;
  598. }
  599. protected void Error_ConditionalAttributeIsNotValid ()
  600. {
  601. Report.Error (577, Location,
  602. "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
  603. GetSignatureForError ());
  604. }
  605. public bool IsPartialDefinition {
  606. get {
  607. return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
  608. }
  609. }
  610. public bool IsPartialImplementation {
  611. get {
  612. return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
  613. }
  614. }
  615. public override string[] ValidAttributeTargets {
  616. get {
  617. return attribute_targets;
  618. }
  619. }
  620. #region IMethodData Members
  621. bool IMethodData.IsAccessor {
  622. get {
  623. return false;
  624. }
  625. }
  626. public TypeSpec ReturnType {
  627. get {
  628. return MemberType;
  629. }
  630. }
  631. public MemberName MethodName {
  632. get {
  633. return MemberName;
  634. }
  635. }
  636. /// <summary>
  637. /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
  638. /// </summary>
  639. public override string[] ConditionalConditions ()
  640. {
  641. if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
  642. return null;
  643. if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.Excluded) != 0)
  644. return new string [0];
  645. caching_flags &= ~Flags.Excluded_Undetected;
  646. string[] conditions;
  647. if (base_method == null) {
  648. if (OptAttributes == null)
  649. return null;
  650. Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
  651. if (attrs == null)
  652. return null;
  653. conditions = new string[attrs.Length];
  654. for (int i = 0; i < conditions.Length; ++i)
  655. conditions[i] = attrs[i].GetConditionalAttributeValue ();
  656. } else {
  657. conditions = base_method.MemberDefinition.ConditionalConditions();
  658. }
  659. if (conditions != null)
  660. caching_flags |= Flags.Excluded;
  661. return conditions;
  662. }
  663. #endregion
  664. public virtual void PrepareEmit ()
  665. {
  666. var mb = MethodData.DefineMethodBuilder (Parent);
  667. if (CurrentTypeParameters != null) {
  668. string[] gnames = new string[CurrentTypeParameters.Count];
  669. for (int i = 0; i < gnames.Length; ++i) {
  670. gnames[i] = CurrentTypeParameters[i].Name;
  671. }
  672. var gen_params = MethodBuilder.DefineGenericParameters (gnames);
  673. for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
  674. var tp = CurrentTypeParameters[i];
  675. tp.Define (gen_params[i]);
  676. }
  677. }
  678. //
  679. // Generic method has been already defined to resolve method parameters
  680. // correctly when they use type parameters
  681. //
  682. mb.SetParameters (parameters.GetMetaInfo ());
  683. mb.SetReturnType (ReturnType.GetMetaInfo ());
  684. }
  685. public override void WriteDebugSymbol (MonoSymbolFile file)
  686. {
  687. if (MethodData != null && !IsPartialDefinition)
  688. MethodData.WriteDebugSymbol (file);
  689. }
  690. }
  691. public class Method : MethodOrOperator, IGenericMethodDefinition
  692. {
  693. Method partialMethodImplementation;
  694. public Method (TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, MemberName name, ParametersCompiled parameters, Attributes attrs)
  695. : base (parent, return_type, mod,
  696. parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
  697. parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct | Modifiers.ASYNC :
  698. AllowedModifiersClass | Modifiers.ASYNC,
  699. name, attrs, parameters)
  700. {
  701. }
  702. protected Method (TypeDefinition parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
  703. MemberName name, ParametersCompiled parameters, Attributes attrs)
  704. : base (parent, return_type, mod, amod, name, attrs, parameters)
  705. {
  706. }
  707. #region Properties
  708. public override TypeParameters CurrentTypeParameters {
  709. get {
  710. return MemberName.TypeParameters;
  711. }
  712. }
  713. public TypeParameterSpec[] TypeParameters {
  714. get {
  715. return CurrentTypeParameters.Types;
  716. }
  717. }
  718. public int TypeParametersCount {
  719. get {
  720. return CurrentTypeParameters == null ? 0 : CurrentTypeParameters.Count;
  721. }
  722. }
  723. #endregion
  724. public override void Accept (StructuralVisitor visitor)
  725. {
  726. visitor.Visit (this);
  727. }
  728. public static Method Create (TypeDefinition parent, FullNamedExpression returnType, Modifiers mod,
  729. MemberName name, ParametersCompiled parameters, Attributes attrs)
  730. {
  731. var m = new Method (parent, returnType, mod, name, parameters, attrs);
  732. if ((mod & Modifiers.PARTIAL) != 0) {
  733. const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN |
  734. Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
  735. if ((mod & invalid_partial_mod) != 0) {
  736. m.Report.Error (750, m.Location,
  737. "A partial method cannot define access modifier or any of abstract, extern, new, override, sealed, or virtual modifiers");
  738. mod &= ~invalid_partial_mod;
  739. }
  740. if ((parent.ModFlags & Modifiers.PARTIAL) == 0) {
  741. m.Report.Error (751, m.Location,
  742. "A partial method must be declared within a partial class or partial struct");
  743. }
  744. }
  745. if ((mod & Modifiers.STATIC) == 0 && parameters.HasExtensionMethodType) {
  746. m.Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static",
  747. m.GetSignatureForError ());
  748. }
  749. return m;
  750. }
  751. public override string GetSignatureForError()
  752. {
  753. return base.GetSignatureForError () + parameters.GetSignatureForError ();
  754. }
  755. void Error_DuplicateEntryPoint (Method b)
  756. {
  757. Report.Error (17, b.Location,
  758. "Program `{0}' has more than one entry point defined: `{1}'",
  759. b.Module.Builder.ScopeName, b.GetSignatureForError ());
  760. }
  761. bool IsEntryPoint ()
  762. {
  763. if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int)
  764. return false;
  765. if (parameters.IsEmpty)
  766. return true;
  767. if (parameters.Count > 1)
  768. return false;
  769. var ac = parameters.Types [0] as ArrayContainer;
  770. return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String &&
  771. (parameters[0].ModFlags & Parameter.Modifier.RefOutMask) == 0;
  772. }
  773. public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
  774. {
  775. if (arity == 0) {
  776. var tp = CurrentTypeParameters;
  777. if (tp != null) {
  778. TypeParameter t = tp.Find (name);
  779. if (t != null)
  780. return new TypeParameterExpr (t, loc);
  781. }
  782. }
  783. return base.LookupNamespaceOrType (name, arity, mode, loc);
  784. }
  785. public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  786. {
  787. if (a.Type == pa.Conditional) {
  788. if (IsExplicitImpl) {
  789. Error_ConditionalAttributeIsNotValid ();
  790. return;
  791. }
  792. if ((ModFlags & Modifiers.OVERRIDE) != 0) {
  793. Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
  794. return;
  795. }
  796. if (ReturnType.Kind != MemberKind.Void) {
  797. Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
  798. return;
  799. }
  800. if (IsInterface) {
  801. Report.Error (582, Location, "Conditional not valid on interface members");
  802. return;
  803. }
  804. if (MethodData.implementing != null) {
  805. Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
  806. Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
  807. GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
  808. return;
  809. }
  810. for (int i = 0; i < parameters.Count; ++i) {
  811. if ((parameters.FixedParameters [i].ModFlags & Parameter.Modifier.OUT) != 0) {
  812. Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
  813. return;
  814. }
  815. }
  816. }
  817. if (a.Type == pa.Extension) {
  818. a.Error_MisusedExtensionAttribute ();
  819. return;
  820. }
  821. base.ApplyAttributeBuilder (a, ctor, cdata, pa);
  822. }
  823. void CreateTypeParameters ()
  824. {
  825. var tparams = MemberName.TypeParameters;
  826. var parent_tparams = Parent.TypeParametersAll;
  827. for (int i = 0; i < MemberName.Arity; i++) {
  828. string type_argument_name = tparams[i].MemberName.Name;
  829. if (block == null) {
  830. int idx = parameters.GetParameterIndexByName (type_argument_name);
  831. if (idx >= 0) {
  832. var b = block;
  833. if (b == null)
  834. b = new ToplevelBlock (Compiler, Location);
  835. b.Error_AlreadyDeclaredTypeParameter (type_argument_name, parameters[i].Location);
  836. }
  837. } else {
  838. INamedBlockVariable variable = null;
  839. block.GetLocalName (type_argument_name, block, ref variable);
  840. if (variable != null)
  841. variable.Block.Error_AlreadyDeclaredTypeParameter (type_argument_name, variable.Location);
  842. }
  843. if (parent_tparams != null) {
  844. var tp = parent_tparams.Find (type_argument_name);
  845. if (tp != null) {
  846. tparams[i].WarningParentNameConflict (tp);
  847. }
  848. }
  849. }
  850. tparams.Create (null, 0, Parent);
  851. }
  852. protected virtual void DefineTypeParameters ()
  853. {
  854. var tparams = CurrentTypeParameters;
  855. TypeParameterSpec[] base_tparams = null;
  856. TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes;
  857. TypeSpec[] base_targs = TypeSpec.EmptyTypes;
  858. if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
  859. MethodSpec base_override = base_method ?? MethodData.implementing;
  860. if (base_override != null) {
  861. base_tparams = base_override.GenericDefinition.TypeParameters;
  862. if (base_override.DeclaringType.IsGeneric) {
  863. base_decl_tparams = base_override.DeclaringType.MemberDefinition.TypeParameters;
  864. if (base_method != null) {
  865. var base_type_parent = CurrentType;
  866. while (base_type_parent.BaseType != base_override.DeclaringType) {
  867. base_type_parent = base_type_parent.BaseType;
  868. }
  869. base_targs = base_type_parent.BaseType.TypeArguments;
  870. } else {
  871. foreach (var iface in Parent.CurrentType.Interfaces) {
  872. if (iface == base_override.DeclaringType) {
  873. base_targs = iface.TypeArguments;
  874. break;
  875. }
  876. }
  877. }
  878. }
  879. if (base_override.IsGeneric) {
  880. ObsoleteAttribute oa;
  881. foreach (var base_tp in base_tparams) {
  882. oa = base_tp.BaseType.GetAttributeObsolete ();
  883. if (oa != null) {
  884. AttributeTester.Report_ObsoleteMessage (oa, base_tp.BaseType.GetSignatureForError (), Location, Report);
  885. }
  886. if (base_tp.InterfacesDefined != null) {
  887. foreach (var iface in base_tp.InterfacesDefined) {
  888. oa = iface.GetAttributeObsolete ();
  889. if (oa != null) {
  890. AttributeTester.Report_ObsoleteMessage (oa, iface.GetSignatureForError (), Location, Report);
  891. }
  892. }
  893. }
  894. }
  895. if (base_decl_tparams.Length != 0) {
  896. base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray ();
  897. base_targs = base_targs.Concat (tparams.Types).ToArray ();
  898. } else {
  899. base_decl_tparams = base_tparams;
  900. base_targs = tparams.Types;
  901. }
  902. }
  903. }
  904. }
  905. for (int i = 0; i < tparams.Count; ++i) {
  906. var tp = tparams [i];
  907. if (base_tparams == null) {
  908. tp.ResolveConstraints (this);
  909. continue;
  910. }
  911. //
  912. // Copy base constraints for override/explicit methods
  913. //
  914. var base_tparam = base_tparams [i];
  915. var local_tparam = tp.Type;
  916. local_tparam.SpecialConstraint = base_tparam.SpecialConstraint;
  917. var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs);
  918. base_tparam.InflateConstraints (inflator, local_tparam);
  919. //
  920. // Check all type argument constraints for possible collision or unification
  921. // introduced by inflating inherited constraints in this context
  922. //
  923. // Conflict example:
  924. //
  925. // class A<T> { virtual void Foo<U> () where U : class, T {} }
  926. // class B : A<int> { override void Foo<U> {} }
  927. //
  928. var local_tparam_targs = local_tparam.TypeArguments;
  929. if (local_tparam_targs != null) {
  930. for (int ii = 0; ii < local_tparam_targs.Length; ++ii) {
  931. var ta = local_tparam_targs [ii];
  932. if (!ta.IsClass && !ta.IsStruct)
  933. continue;
  934. TypeSpec[] unique_tparams = null;
  935. for (int iii = ii + 1; iii < local_tparam_targs.Length; ++iii) {
  936. //
  937. // Remove any identical or unified constraint types
  938. //
  939. var tparam_checked = local_tparam_targs [iii];
  940. if (TypeSpecComparer.IsEqual (ta, tparam_checked) || TypeSpec.IsBaseClass (ta, tparam_checked, false)) {
  941. unique_tparams = new TypeSpec[local_tparam_targs.Length - 1];
  942. Array.Copy (local_tparam_targs, 0, unique_tparams, 0, iii);
  943. Array.Copy (local_tparam_targs, iii + 1, unique_tparams, iii, local_tparam_targs.Length - iii - 1);
  944. } else if (!TypeSpec.IsBaseClass (tparam_checked, ta, false)) {
  945. Constraints.Error_ConflictingConstraints (this, local_tparam, ta, tparam_checked, Location);
  946. }
  947. }
  948. if (unique_tparams != null) {
  949. local_tparam_targs = unique_tparams;
  950. local_tparam.TypeArguments = local_tparam_targs;
  951. continue;
  952. }
  953. Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location);
  954. }
  955. }
  956. }
  957. if (base_tparams == null && MethodData != null && MethodData.implementing != null) {
  958. CheckImplementingMethodConstraints (Parent, spec, MethodData.implementing);
  959. }
  960. }
  961. public static bool CheckImplementingMethodConstraints (TypeContainer container, MethodSpec method, MethodSpec baseMethod)
  962. {
  963. var tparams = method.Constraints;
  964. var base_tparams = baseMethod.Constraints;
  965. for (int i = 0; i < tparams.Length; ++i) {
  966. if (!tparams[i].HasSameConstraintsImplementation (base_tparams[i])) {
  967. container.Compiler.Report.SymbolRelatedToPreviousError (method);
  968. container.Compiler.Report.SymbolRelatedToPreviousError (baseMethod);
  969. // Using container location because the interface can be implemented
  970. // by base class
  971. var tp = (tparams [i].MemberDefinition as MemberCore) ?? container;
  972. container.Compiler.Report.Error (425, tp.Location,
  973. "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",
  974. tparams[i].GetSignatureForError (), method.GetSignatureForError (),
  975. base_tparams[i].GetSignatureForError (), baseMethod.GetSignatureForError ());
  976. return false;
  977. }
  978. }
  979. return true;
  980. }
  981. //
  982. // Creates the type
  983. //
  984. public override bool Define ()
  985. {
  986. if (!base.Define ())
  987. return false;
  988. if (member_type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
  989. Report.Warning (465, 1, Location,
  990. "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
  991. }
  992. if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) {
  993. Error1599 (Location, ReturnType, Report);
  994. return false;
  995. }
  996. if (CurrentTypeParameters == null) {
  997. if (base_method != null && !IsExplicitImpl) {
  998. if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && MemberName.Name == "Equals")
  999. Parent.PartialContainer.Mark_HasEquals ();
  1000. else if (parameters.IsEmpty && MemberName.Name == "GetHashCode")
  1001. Parent.PartialContainer.Mark_HasGetHashCode ();
  1002. }
  1003. } else {
  1004. DefineTypeParameters ();
  1005. }
  1006. if (block != null) {
  1007. if (block.IsIterator) {
  1008. //
  1009. // Current method is turned into automatically generated
  1010. // wrapper which creates an instance of iterator
  1011. //
  1012. Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
  1013. ModFlags |= Modifiers.DEBUGGER_HIDDEN;
  1014. }
  1015. if ((ModFlags & Modifiers.ASYNC) != 0) {
  1016. if (ReturnType.Kind != MemberKind.Void &&
  1017. ReturnType != Module.PredefinedTypes.Task.TypeSpec &&
  1018. !ReturnType.IsGenericTask) {
  1019. Report.Error (1983, Location, "The return type of an async method must be void, Task, or Task<T>");
  1020. }
  1021. block = (ToplevelBlock) block.ConvertToAsyncTask (this, Parent.PartialContainer, parameters, ReturnType, null, Location);
  1022. ModFlags |= Modifiers.DEBUGGER_STEP_THROUGH;
  1023. }
  1024. if (Compiler.Settings.WriteMetadataOnly)
  1025. block = null;
  1026. }
  1027. if ((ModFlags & Modifiers.STATIC) == 0)
  1028. return true;
  1029. if (parameters.HasExtensionMethodType) {
  1030. if (Parent.PartialContainer.IsStatic && !Parent.IsGenericOrParentIsGeneric) {
  1031. if (!Parent.IsTopLevel)
  1032. Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
  1033. GetSignatureForError ());
  1034. PredefinedAttribute pa = Module.PredefinedAttributes.Extension;
  1035. if (!pa.IsDefined) {
  1036. Report.Error (1110, Location,
  1037. "`{0}': Extension methods require `System.Runtime.CompilerServices.ExtensionAttribute' type to be available. Are you missing an assembly reference?",
  1038. GetSignatureForError ());
  1039. }
  1040. ModFlags |= Modifiers.METHOD_EXTENSION;
  1041. Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
  1042. Spec.DeclaringType.SetExtensionMethodContainer ();
  1043. Parent.Module.HasExtensionMethod = true;
  1044. } else {
  1045. Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
  1046. GetSignatureForError ());
  1047. }
  1048. }
  1049. //
  1050. // This is used to track the Entry Point,
  1051. //
  1052. var settings = Compiler.Settings;
  1053. if (settings.NeedsEntryPoint && MemberName.Name == "Main" && !IsPartialDefinition && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) {
  1054. if (IsEntryPoint ()) {
  1055. if (Parent.DeclaringAssembly.EntryPoint == null) {
  1056. if (Parent.IsGenericOrParentIsGeneric || MemberName.IsGeneric) {
  1057. Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
  1058. GetSignatureForError ());
  1059. } else if ((ModFlags & Modifiers.ASYNC) != 0) {
  1060. Report.Error (4009, Location, "`{0}': an entry point cannot be async method",
  1061. GetSignatureForError ());
  1062. } else {
  1063. SetIsUsed ();
  1064. Parent.DeclaringAssembly.EntryPoint = this;
  1065. }
  1066. } else {
  1067. Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint);
  1068. Error_DuplicateEntryPoint (this);
  1069. }
  1070. } else {
  1071. Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
  1072. GetSignatureForError ());
  1073. }
  1074. }
  1075. return true;
  1076. }
  1077. public override void PrepareEmit ()
  1078. {
  1079. if (IsPartialDefinition) {
  1080. //
  1081. // Use partial method implementation builder for partial method declaration attributes
  1082. //
  1083. if (partialMethodImplementation != null) {
  1084. MethodData = partialMethodImplementation.MethodData;
  1085. }
  1086. return;
  1087. }
  1088. base.PrepareEmit ();
  1089. }
  1090. //
  1091. // Emits the code
  1092. //
  1093. public override void Emit ()
  1094. {
  1095. try {
  1096. if (IsPartialDefinition) {
  1097. if (partialMethodImplementation != null && CurrentTypeParameters != null) {
  1098. CurrentTypeParameters.CheckPartialConstraints (partialMethodImplementation);
  1099. var otp = partialMethodImplementation.CurrentTypeParameters;
  1100. for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
  1101. var tp = CurrentTypeParameters [i];
  1102. tp.Define (otp[i]);
  1103. }
  1104. }
  1105. return;
  1106. }
  1107. if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
  1108. Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
  1109. GetSignatureForError ());
  1110. }
  1111. if (CurrentTypeParameters != null) {
  1112. for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
  1113. var tp = CurrentTypeParameters [i];
  1114. tp.CheckGenericConstraints (false);
  1115. tp.Emit ();
  1116. }
  1117. }
  1118. if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
  1119. Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder);
  1120. base.Emit ();
  1121. } catch (Exception e) {
  1122. throw new InternalErrorException (this, e);
  1123. }
  1124. }
  1125. public override bool EnableOverloadChecks (MemberCore overload)
  1126. {
  1127. if (overload is Indexer)
  1128. return false;
  1129. return base.EnableOverloadChecks (overload);
  1130. }
  1131. public static void Error1599 (Location loc, TypeSpec t, Report Report)
  1132. {
  1133. Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", t.GetSignatureForError ());
  1134. }
  1135. protected override bool ResolveMemberType ()
  1136. {
  1137. if (CurrentTypeParameters != null) {
  1138. CreateTypeParameters ();
  1139. }
  1140. return base.ResolveMemberType ();
  1141. }
  1142. public void SetPartialDefinition (Method methodDefinition)
  1143. {
  1144. caching_flags |= Flags.PartialDefinitionExists;
  1145. methodDefinition.partialMethodImplementation = this;
  1146. // Ensure we are always using method declaration parameters
  1147. for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
  1148. var md_p = methodDefinition.parameters [i];
  1149. var p = parameters [i];
  1150. p.Name = md_p.Name;
  1151. p.DefaultValue = md_p.DefaultValue;
  1152. if (md_p.OptAttributes != null) {
  1153. if (p.OptAttributes == null) {
  1154. p.OptAttributes = md_p.OptAttributes;
  1155. } else {
  1156. p.OptAttributes.Attrs.AddRange (md_p.OptAttributes.Attrs);
  1157. }
  1158. }
  1159. }
  1160. if (methodDefinition.attributes != null) {
  1161. if (attributes == null) {
  1162. attributes = methodDefinition.attributes;
  1163. } else {
  1164. attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
  1165. }
  1166. }
  1167. if (CurrentTypeParameters != null) {
  1168. for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
  1169. var tp_other = methodDefinition.CurrentTypeParameters [i];
  1170. if (tp_other.OptAttributes == null)
  1171. continue;
  1172. var tp = CurrentTypeParameters [i];
  1173. if (tp.OptAttributes == null) {
  1174. tp.OptAttributes = tp_other.OptAttributes;
  1175. } else {
  1176. tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
  1177. }
  1178. }
  1179. }
  1180. }
  1181. }
  1182. public abstract class ConstructorInitializer : ExpressionStatement
  1183. {
  1184. Arguments argument_list;
  1185. MethodSpec base_ctor;
  1186. protected ConstructorInitializer (Arguments argument_list, Location loc)
  1187. {
  1188. this.argument_list = argument_list;
  1189. this.loc = loc;
  1190. }
  1191. public Arguments Arguments {
  1192. get {
  1193. return argument_list;
  1194. }
  1195. }
  1196. public override bool ContainsEmitWithAwait ()
  1197. {
  1198. throw new NotSupportedException ();
  1199. }
  1200. public override Expression CreateExpressionTree (ResolveContext ec)
  1201. {
  1202. throw new NotSupportedException ("ET");
  1203. }
  1204. protected override Expression DoResolve (ResolveContext ec)
  1205. {
  1206. eclass = ExprClass.Value;
  1207. // FIXME: Hack
  1208. var caller_builder = (Constructor) ec.MemberContext;
  1209. //
  1210. // Spec mandates that constructor initializer will not have `this' access
  1211. //
  1212. using (ec.Set (ResolveContext.Options.BaseInitializer)) {
  1213. if (argument_list != null) {
  1214. bool dynamic;
  1215. argument_list.Resolve (ec, out dynamic);
  1216. if (dynamic) {
  1217. ec.Report.Error (1975, loc,
  1218. "The constructor call cannot be dynamically dispatched within constructor initializer");
  1219. return null;
  1220. }
  1221. }
  1222. type = ec.CurrentType;
  1223. if (this is ConstructorBaseInitializer) {
  1224. if (ec.CurrentType.BaseType == null)
  1225. return this;
  1226. type = ec.CurrentType.BaseType;
  1227. if (ec.CurrentType.IsStruct) {
  1228. ec.Report.Error (522, loc,
  1229. "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
  1230. return this;
  1231. }
  1232. } else {
  1233. //
  1234. // It is legal to have "this" initializers that take no arguments
  1235. // in structs
  1236. //
  1237. // struct D { public D (int a) : this () {}
  1238. //
  1239. if (ec.CurrentType.IsStruct && argument_list == null)
  1240. return this;
  1241. }
  1242. base_ctor = ConstructorLookup (ec, type, ref argument_list, loc);
  1243. }
  1244. if (base_ctor != null && base_ctor.MemberDefinition == caller_builder.Spec.MemberDefinition) {
  1245. ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
  1246. caller_builder.GetSignatureForError ());
  1247. }
  1248. return this;
  1249. }
  1250. public override void Emit (EmitContext ec)
  1251. {
  1252. //
  1253. // It can be null for struct initializers or System.Object
  1254. //
  1255. if (base_ctor == null) {
  1256. if (type == ec.BuiltinTypes.Object)
  1257. return;
  1258. ec.Emit (OpCodes.Ldarg_0);
  1259. ec.Emit (OpCodes.Initobj, type);
  1260. return;
  1261. }
  1262. var call = new CallEmitter ();
  1263. call.InstanceExpression = new CompilerGeneratedThis (type, loc);
  1264. call.EmitPredefined (ec, base_ctor, argument_list, false);
  1265. }
  1266. public override void EmitStatement (EmitContext ec)
  1267. {
  1268. Emit (ec);
  1269. }
  1270. public override void FlowAnalysis (FlowAnalysisContext fc)
  1271. {
  1272. if (argument_list != null)
  1273. argument_list.FlowAnalysis (fc);
  1274. }
  1275. }
  1276. public class ConstructorBaseInitializer : ConstructorInitializer {
  1277. public ConstructorBaseInitializer (Arguments argument_list, Location l) :
  1278. base (argument_list, l)
  1279. {
  1280. }
  1281. }
  1282. class GeneratedBaseInitializer: ConstructorBaseInitializer {
  1283. public GeneratedBaseInitializer (Location loc, Arguments arguments)
  1284. : base (arguments, loc)
  1285. {
  1286. }
  1287. }
  1288. public class ConstructorThisInitializer : ConstructorInitializer {
  1289. public ConstructorThisInitializer (Arguments argument_list, Location l) :
  1290. base (argument_list, l)
  1291. {
  1292. }
  1293. }
  1294. public class Constructor : MethodCore, IMethodData, IMethodDefinition
  1295. {
  1296. public ConstructorBuilder ConstructorBuilder;
  1297. public ConstructorInitializer Initializer;
  1298. SecurityType declarative_security;
  1299. bool has_compliant_args;
  1300. SourceMethodBuilder debug_builder;
  1301. // <summary>
  1302. // Modifiers allowed for a constructor.
  1303. // </summary>
  1304. public const Modifiers AllowedModifiers =
  1305. Modifiers.PUBLIC |
  1306. Modifiers.PROTECTED |
  1307. Modifiers.INTERNAL |
  1308. Modifiers.STATIC |
  1309. Modifiers.UNSAFE |
  1310. Modifiers.EXTERN |
  1311. Modifiers.PRIVATE;
  1312. static readonly string[] attribute_targets = new string [] { "method" };
  1313. public static readonly string ConstructorName = ".ctor";
  1314. public static readonly string TypeConstructorName = ".cctor";
  1315. public Constructor (TypeDefinition parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, Location loc)
  1316. : base (parent, null, mod, AllowedModifiers, new MemberName (name, loc), attrs, args)
  1317. {
  1318. }
  1319. public bool HasCompliantArgs {
  1320. get {
  1321. return has_compliant_args;
  1322. }
  1323. }
  1324. public override AttributeTargets AttributeTargets {
  1325. get {
  1326. return AttributeTargets.Constructor;
  1327. }
  1328. }
  1329. bool IMethodData.IsAccessor {
  1330. get {
  1331. return false;
  1332. }
  1333. }
  1334. public bool IsPrimaryConstructor { get; set; }
  1335. MethodBase IMethodDefinition.Metadata {
  1336. get {
  1337. return ConstructorBuilder;
  1338. }
  1339. }
  1340. //
  1341. // Returns true if this is a default constructor
  1342. //
  1343. public bool IsDefault ()
  1344. {
  1345. if ((ModFlags & Modifiers.STATIC) != 0)
  1346. return parameters.IsEmpty;
  1347. return parameters.IsEmpty &&
  1348. (Initializer is ConstructorBaseInitializer) &&
  1349. (Initializer.Arguments == null);
  1350. }
  1351. public override void Accept (StructuralVisitor visitor)
  1352. {
  1353. visitor.Visit (this);
  1354. }
  1355. public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  1356. {
  1357. if (a.IsValidSecurityAttribute ()) {
  1358. a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
  1359. return;
  1360. }
  1361. if (a.Type == pa.MethodImpl) {
  1362. is_external_implementation = a.IsInternalCall ();
  1363. }
  1364. ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
  1365. }
  1366. protected override bool CheckBase ()
  1367. {
  1368. if ((ModFlags & Modifiers.STATIC) != 0) {
  1369. if (!parameters.IsEmpty) {
  1370. Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
  1371. GetSignatureForError ());
  1372. return false;
  1373. }
  1374. if ((caching_flags & Flags.MethodOverloadsExist) != 0)
  1375. Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
  1376. // the rest can be ignored
  1377. return true;
  1378. }
  1379. // Check whether arguments were correct.
  1380. if (!DefineParameters (parameters))
  1381. return false;
  1382. if ((caching_flags & Flags.MethodOverloadsExist) != 0)
  1383. Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
  1384. if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) {
  1385. Report.Error (568, Location,
  1386. "Structs cannot contain explicit parameterless constructors");
  1387. return false;
  1388. }
  1389. CheckProtectedModifier ();
  1390. return true;
  1391. }
  1392. //
  1393. // Creates the ConstructorBuilder
  1394. //
  1395. public override bool Define ()
  1396. {
  1397. if (ConstructorBuilder != null)
  1398. return true;
  1399. if (!CheckAbstractAndExtern (block != null))
  1400. return false;
  1401. // Check if arguments were correct.
  1402. if (!CheckBase ())
  1403. return false;
  1404. if (Parent.PrimaryConstructorParameters != null && !IsPrimaryConstructor && !IsStatic) {
  1405. if (Parent.Kind == MemberKind.Struct && Initializer is ConstructorThisInitializer && Initializer.Arguments == null) {
  1406. Report.Error (8043, Location, "`{0}': Structs with primary constructor cannot specify default constructor initializer",
  1407. GetSignatureForError ());
  1408. } else if (Initializer == null || Initializer is ConstructorBaseInitializer) {
  1409. Report.Error (8037, Location, "`{0}': Instance constructor of type with primary constructor must specify `this' constructor initializer",
  1410. GetSignatureForError ());
  1411. }
  1412. }
  1413. var ca = ModifiersExtensions.MethodAttr (ModFlags) | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
  1414. ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
  1415. ca, CallingConventions,
  1416. parameters.GetMetaInfo ());
  1417. spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, parameters, ModFlags);
  1418. Parent.MemberCache.AddMember (spec);
  1419. if (block != null) {
  1420. // It's here only to report an error
  1421. if (block.IsIterator) {
  1422. member_type = Compiler.BuiltinTypes.Void;
  1423. Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
  1424. }
  1425. if (Compiler.Settings.WriteMetadataOnly)
  1426. block = null;
  1427. }
  1428. return true;
  1429. }
  1430. //
  1431. // Emits the code
  1432. //
  1433. public o