PageRenderTime 78ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/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
Possible License(s): LGPL-2.1, MIT, CC-BY-SA-3.0
  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 override void Emit ()
  1434. {
  1435. if (Parent.PartialContainer.IsComImport) {
  1436. if (!IsDefault ()) {
  1437. Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
  1438. Parent.GetSignatureForError ());
  1439. }
  1440. // Set as internal implementation and reset block data
  1441. // to ensure no IL is generated
  1442. ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
  1443. block = null;
  1444. }
  1445. if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
  1446. Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder);
  1447. if (OptAttributes != null)
  1448. OptAttributes.Emit ();
  1449. base.Emit ();
  1450. parameters.ApplyAttributes (this, ConstructorBuilder);
  1451. BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void);
  1452. bc.Set (ResolveContext.Options.ConstructorScope);
  1453. if (block != null) {
  1454. if (!IsStatic && Initializer == null && Parent.PartialContainer.Kind == MemberKind.Struct) {
  1455. //
  1456. // If this is a non-static `struct' constructor and doesn't have any
  1457. // initializer, it must initialize all of the struct's fields.
  1458. //
  1459. block.AddThisVariable (bc);
  1460. }
  1461. //
  1462. // If we use a "this (...)" constructor initializer, then
  1463. // do not emit field initializers, they are initialized in the other constructor
  1464. //
  1465. if (!(Initializer is ConstructorThisInitializer))
  1466. Parent.PartialContainer.ResolveFieldInitializers (bc);
  1467. if (!IsStatic) {
  1468. if (Initializer == null && Parent.PartialContainer.Kind == MemberKind.Class) {
  1469. Initializer = new GeneratedBaseInitializer (Location, null);
  1470. }
  1471. if (Initializer != null) {
  1472. //
  1473. // mdb format does not support reqions. Try to workaround this by emitting the
  1474. // sequence point at initializer. Any breakpoint at constructor header should
  1475. // be adjusted to this sequence point as it's the next one which follows.
  1476. //
  1477. block.AddScopeStatement (new StatementExpression (Initializer));
  1478. }
  1479. }
  1480. if (block.Resolve (bc, this)) {
  1481. debug_builder = Parent.CreateMethodSymbolEntry ();
  1482. EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType, debug_builder);
  1483. ec.With (EmitContext.Options.ConstructorScope, true);
  1484. block.Emit (ec);
  1485. }
  1486. }
  1487. if (declarative_security != null) {
  1488. foreach (var de in declarative_security) {
  1489. #if STATIC
  1490. ConstructorBuilder.__AddDeclarativeSecurity (de);
  1491. #else
  1492. ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
  1493. #endif
  1494. }
  1495. }
  1496. block = null;
  1497. }
  1498. protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
  1499. {
  1500. // Is never override
  1501. bestCandidate = null;
  1502. return null;
  1503. }
  1504. public override string GetCallerMemberName ()
  1505. {
  1506. return IsStatic ? TypeConstructorName : ConstructorName;
  1507. }
  1508. public override string GetSignatureForDocumentation ()
  1509. {
  1510. return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation ();
  1511. }
  1512. public override string GetSignatureForError()
  1513. {
  1514. return base.GetSignatureForError () + parameters.GetSignatureForError ();
  1515. }
  1516. public override string[] ValidAttributeTargets {
  1517. get {
  1518. return attribute_targets;
  1519. }
  1520. }
  1521. protected override bool VerifyClsCompliance ()
  1522. {
  1523. if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
  1524. return false;
  1525. }
  1526. if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
  1527. foreach (TypeSpec param in parameters.Types) {
  1528. if (param.IsArray) {
  1529. return true;
  1530. }
  1531. }
  1532. }
  1533. has_compliant_args = true;
  1534. return true;
  1535. }
  1536. public override void WriteDebugSymbol (MonoSymbolFile file)
  1537. {
  1538. if (debug_builder == null)
  1539. return;
  1540. var token = ConstructorBuilder.GetToken ();
  1541. int t = token.Token;
  1542. #if STATIC
  1543. if (ModuleBuilder.IsPseudoToken (t))
  1544. t = Module.Builder.ResolvePseudoToken (t);
  1545. #endif
  1546. debug_builder.DefineMethod (file, t);
  1547. }
  1548. #region IMethodData Members
  1549. public MemberName MethodName {
  1550. get {
  1551. return MemberName;
  1552. }
  1553. }
  1554. public TypeSpec ReturnType {
  1555. get {
  1556. return MemberType;
  1557. }
  1558. }
  1559. EmitContext IMethodData.CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
  1560. {
  1561. throw new NotImplementedException ();
  1562. }
  1563. #endregion
  1564. }
  1565. /// <summary>
  1566. /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
  1567. /// </summary>
  1568. public interface IMethodData : IMemberContext
  1569. {
  1570. CallingConventions CallingConventions { get; }
  1571. Location Location { get; }
  1572. MemberName MethodName { get; }
  1573. TypeSpec ReturnType { get; }
  1574. ParametersCompiled ParameterInfo { get; }
  1575. MethodSpec Spec { get; }
  1576. bool IsAccessor { get; }
  1577. Attributes OptAttributes { get; }
  1578. ToplevelBlock Block { get; set; }
  1579. EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod);
  1580. }
  1581. //
  1582. // Encapsulates most of the Method's state
  1583. //
  1584. public class MethodData
  1585. {
  1586. public readonly IMethodData method;
  1587. //
  1588. // Are we implementing an interface ?
  1589. //
  1590. public MethodSpec implementing;
  1591. //
  1592. // Protected data.
  1593. //
  1594. protected InterfaceMemberBase member;
  1595. protected Modifiers modifiers;
  1596. protected MethodAttributes flags;
  1597. protected TypeSpec declaring_type;
  1598. protected MethodSpec parent_method;
  1599. SourceMethodBuilder debug_builder;
  1600. string full_name;
  1601. MethodBuilder builder;
  1602. public MethodBuilder MethodBuilder {
  1603. get {
  1604. return builder;
  1605. }
  1606. }
  1607. public TypeSpec DeclaringType {
  1608. get {
  1609. return declaring_type;
  1610. }
  1611. }
  1612. public string MetadataName {
  1613. get {
  1614. return full_name;
  1615. }
  1616. }
  1617. public MethodData (InterfaceMemberBase member,
  1618. Modifiers modifiers, MethodAttributes flags, IMethodData method)
  1619. {
  1620. this.member = member;
  1621. this.modifiers = modifiers;
  1622. this.flags = flags;
  1623. this.method = method;
  1624. }
  1625. public MethodData (InterfaceMemberBase member,
  1626. Modifiers modifiers, MethodAttributes flags,
  1627. IMethodData method,
  1628. MethodSpec parent_method)
  1629. : this (member, modifiers, flags, method)
  1630. {
  1631. this.parent_method = parent_method;
  1632. }
  1633. public bool Define (TypeDefinition container, string method_full_name)
  1634. {
  1635. PendingImplementation pending = container.PendingImplementations;
  1636. MethodSpec ambig_iface_method;
  1637. bool optional = false;
  1638. if (pending != null) {
  1639. implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method, ref optional);
  1640. if (member.InterfaceType != null) {
  1641. if (implementing == null) {
  1642. if (member is PropertyBase) {
  1643. container.Compiler.Report.Error (550, method.Location,
  1644. "`{0}' is an accessor not found in interface member `{1}{2}'",
  1645. method.GetSignatureForError (), member.InterfaceType.GetSignatureForError (),
  1646. member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
  1647. } else {
  1648. container.Compiler.Report.Error (539, method.Location,
  1649. "`{0}.{1}' in explicit interface declaration is not a member of interface",
  1650. member.InterfaceType.GetSignatureForError (), member.ShortName);
  1651. }
  1652. return false;
  1653. }
  1654. if (implementing.IsAccessor && !method.IsAccessor) {
  1655. container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
  1656. container.Compiler.Report.Error (683, method.Location,
  1657. "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
  1658. member.GetSignatureForError (), implementing.GetSignatureForError ());
  1659. return false;
  1660. }
  1661. } else {
  1662. if (implementing != null && !optional) {
  1663. if (!method.IsAccessor) {
  1664. if (implementing.IsAccessor) {
  1665. container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
  1666. container.Compiler.Report.Error (470, method.Location,
  1667. "Method `{0}' cannot implement interface accessor `{1}'",
  1668. method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
  1669. }
  1670. } else if (implementing.DeclaringType.IsInterface) {
  1671. if (!implementing.IsAccessor) {
  1672. container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
  1673. container.Compiler.Report.Error (686, method.Location,
  1674. "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
  1675. method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
  1676. } else {
  1677. PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod;
  1678. if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
  1679. container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
  1680. container.Compiler.Report.Error (277, method.Location,
  1681. "Accessor `{0}' must be declared public to implement interface member `{1}'",
  1682. method.GetSignatureForError (), implementing.GetSignatureForError ());
  1683. }
  1684. }
  1685. }
  1686. }
  1687. }
  1688. } else {
  1689. ambig_iface_method = null;
  1690. }
  1691. //
  1692. // For implicit implementations, make sure we are public, for
  1693. // explicit implementations, make sure we are private.
  1694. //
  1695. if (implementing != null){
  1696. if (member.IsExplicitImpl) {
  1697. if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
  1698. container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
  1699. container.Compiler.Report.Error (466, method.Location,
  1700. "`{0}': the explicit interface implementation cannot introduce the params modifier",
  1701. method.GetSignatureForError ());
  1702. }
  1703. if (ambig_iface_method != null) {
  1704. container.Compiler.Report.SymbolRelatedToPreviousError (ambig_iface_method);
  1705. container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
  1706. container.Compiler.Report.Warning (473, 2, method.Location,
  1707. "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead",
  1708. method.GetSignatureForError ());
  1709. }
  1710. } else {
  1711. //
  1712. // Setting implementin to null inside this block will trigger a more
  1713. // verbose error reporting for missing interface implementations
  1714. //
  1715. if (implementing.DeclaringType.IsInterface) {
  1716. //
  1717. // If this is an interface method implementation,
  1718. // check for public accessibility
  1719. //
  1720. if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) {
  1721. implementing = null;
  1722. } else if (optional && (container.Interfaces == null || !container.Definition.Interfaces.Contains (implementing.DeclaringType))) {
  1723. //
  1724. // We are not implementing interface when base class already implemented it
  1725. //
  1726. implementing = null;
  1727. }
  1728. } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
  1729. // We may never be private.
  1730. implementing = null;
  1731. } else if ((modifiers & Modifiers.OVERRIDE) == 0) {
  1732. //
  1733. // We may be protected if we're overriding something.
  1734. //
  1735. implementing = null;
  1736. }
  1737. }
  1738. //
  1739. // Static is not allowed
  1740. //
  1741. if ((modifiers & Modifiers.STATIC) != 0){
  1742. implementing = null;
  1743. }
  1744. }
  1745. //
  1746. // If implementing is still valid, set flags
  1747. //
  1748. if (implementing != null){
  1749. //
  1750. // When implementing interface methods, set NewSlot
  1751. // unless, we are overwriting a method.
  1752. //
  1753. if ((modifiers & Modifiers.OVERRIDE) == 0 && implementing.DeclaringType.IsInterface) {
  1754. flags |= MethodAttributes.NewSlot;
  1755. }
  1756. flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
  1757. // Set Final unless we're virtual, abstract or already overriding a method.
  1758. if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
  1759. flags |= MethodAttributes.Final;
  1760. //
  1761. // clear the pending implementation flag (requires explicit methods to be defined first)
  1762. //
  1763. pending.ImplementMethod (method.MethodName,
  1764. member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method, ref optional);
  1765. //
  1766. // Update indexer accessor name to match implementing abstract accessor
  1767. //
  1768. if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
  1769. method_full_name = implementing.MemberDefinition.Name;
  1770. }
  1771. full_name = method_full_name;
  1772. declaring_type = container.Definition;
  1773. return true;
  1774. }
  1775. void DefineOverride (TypeDefinition container)
  1776. {
  1777. if (implementing == null)
  1778. return;
  1779. if (!member.IsExplicitImpl)
  1780. return;
  1781. container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
  1782. }
  1783. //
  1784. // Creates partial MethodBuilder for the method when has generic parameters used
  1785. // as arguments or return type
  1786. //
  1787. public MethodBuilder DefineMethodBuilder (TypeDefinition container)
  1788. {
  1789. if (builder != null)
  1790. throw new InternalErrorException ();
  1791. builder = container.TypeBuilder.DefineMethod (full_name, flags, method.CallingConventions);
  1792. return builder;
  1793. }
  1794. //
  1795. // Creates full MethodBuilder for the method
  1796. //
  1797. public MethodBuilder DefineMethodBuilder (TypeDefinition container, ParametersCompiled param)
  1798. {
  1799. DefineMethodBuilder (container);
  1800. builder.SetReturnType (method.ReturnType.GetMetaInfo ());
  1801. builder.SetParameters (param.GetMetaInfo ());
  1802. return builder;
  1803. }
  1804. //
  1805. // Emits the code
  1806. //
  1807. public void Emit (TypeDefinition parent)
  1808. {
  1809. DefineOverride (parent);
  1810. method.ParameterInfo.ApplyAttributes (method, MethodBuilder);
  1811. ToplevelBlock block = method.Block;
  1812. if (block != null) {
  1813. BlockContext bc = new BlockContext (method, block, method.ReturnType);
  1814. if (block.Resolve (bc, method)) {
  1815. debug_builder = member.Parent.CreateMethodSymbolEntry ();
  1816. EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator (), debug_builder);
  1817. block.Emit (ec);
  1818. }
  1819. }
  1820. }
  1821. public void WriteDebugSymbol (MonoSymbolFile file)
  1822. {
  1823. if (debug_builder == null)
  1824. return;
  1825. var token = builder.GetToken ();
  1826. int t = token.Token;
  1827. #if STATIC
  1828. if (ModuleBuilder.IsPseudoToken (t))
  1829. t = member.Module.Builder.ResolvePseudoToken (t);
  1830. #endif
  1831. debug_builder.DefineMethod (file, t);
  1832. }
  1833. }
  1834. public class Destructor : MethodOrOperator
  1835. {
  1836. const Modifiers AllowedModifiers =
  1837. Modifiers.UNSAFE |
  1838. Modifiers.EXTERN;
  1839. static readonly string[] attribute_targets = new string [] { "method" };
  1840. public static readonly string MetadataName = "Finalize";
  1841. public string Identifier {
  1842. get;
  1843. set;
  1844. }
  1845. public Destructor (TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
  1846. : base (parent, null, mod, AllowedModifiers, new MemberName (MetadataName, l), attrs, parameters)
  1847. {
  1848. ModFlags &= ~Modifiers.PRIVATE;
  1849. ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
  1850. }
  1851. public override void Accept (StructuralVisitor visitor)
  1852. {
  1853. visitor.Visit (this);
  1854. }
  1855. public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  1856. {
  1857. if (a.Type == pa.Conditional) {
  1858. Error_ConditionalAttributeIsNotValid ();
  1859. return;
  1860. }
  1861. base.ApplyAttributeBuilder (a, ctor, cdata, pa);
  1862. }
  1863. protected override bool CheckBase ()
  1864. {
  1865. if ((caching_flags & Flags.MethodOverloadsExist) != 0)
  1866. CheckForDuplications ();
  1867. // Don't check base, destructors have special syntax
  1868. return true;
  1869. }
  1870. public override bool Define ()
  1871. {
  1872. base.Define ();
  1873. if (Compiler.Settings.WriteMetadataOnly)
  1874. block = null;
  1875. return true;
  1876. }
  1877. public override void Emit()
  1878. {
  1879. var base_type = Parent.PartialContainer.BaseType;
  1880. if (base_type != null && Block != null) {
  1881. var base_dtor = MemberCache.FindMember (base_type,
  1882. new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
  1883. if (base_dtor == null)
  1884. throw new NotImplementedException ();
  1885. MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
  1886. method_expr.InstanceExpression = new BaseThis (base_type, Location);
  1887. var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation) {
  1888. IsCompilerGenerated = true
  1889. };
  1890. var finaly_block = new ExplicitBlock (block, Location, Location) {
  1891. IsCompilerGenerated = true
  1892. };
  1893. //
  1894. // 0-size arguments to avoid CS0250 error
  1895. // TODO: Should use AddScopeStatement or something else which emits correct
  1896. // debugger scope
  1897. //
  1898. finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)), Location.Null));
  1899. var tf = new TryFinally (try_block, finaly_block, Location);
  1900. block.WrapIntoDestructor (tf, try_block);
  1901. }
  1902. base.Emit ();
  1903. }
  1904. public override string GetSignatureForError ()
  1905. {
  1906. return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
  1907. }
  1908. protected override bool ResolveMemberType ()
  1909. {
  1910. member_type = Compiler.BuiltinTypes.Void;
  1911. return true;
  1912. }
  1913. public override string[] ValidAttributeTargets {
  1914. get {
  1915. return attribute_targets;
  1916. }
  1917. }
  1918. }
  1919. // Ooouh Martin, templates are missing here.
  1920. // When it will be possible move here a lot of child code and template method type.
  1921. public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData, IMethodDefinition {
  1922. protected MethodData method_data;
  1923. protected ToplevelBlock block;
  1924. protected SecurityType declarative_security;
  1925. protected readonly string prefix;
  1926. ReturnParameter return_attributes;
  1927. protected AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
  1928. : base (member.Parent, SetupName (prefix, member, loc), attrs)
  1929. {
  1930. this.prefix = prefix;
  1931. }
  1932. static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
  1933. {
  1934. return new MemberName (member.MemberName.Left, prefix + member.ShortName, member.MemberName.ExplicitInterface, loc);
  1935. }
  1936. public void UpdateName (InterfaceMemberBase member)
  1937. {
  1938. SetMemberName (SetupName (prefix, member, Location));
  1939. }
  1940. #region IMethodData Members
  1941. public ToplevelBlock Block {
  1942. get {
  1943. return block;
  1944. }
  1945. set {
  1946. block = value;
  1947. }
  1948. }
  1949. public CallingConventions CallingConventions {
  1950. get {
  1951. return CallingConventions.Standard;
  1952. }
  1953. }
  1954. public EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
  1955. {
  1956. return new EmitContext (this, ig, ReturnType, sourceMethod);
  1957. }
  1958. public bool IsAccessor {
  1959. get {
  1960. return true;
  1961. }
  1962. }
  1963. public MemberName MethodName {
  1964. get {
  1965. return MemberName;
  1966. }
  1967. }
  1968. public TypeSpec[] ParameterTypes {
  1969. get {
  1970. return ParameterInfo.Types;
  1971. }
  1972. }
  1973. MethodBase IMethodDefinition.Metadata {
  1974. get {
  1975. return method_data.MethodBuilder;
  1976. }
  1977. }
  1978. public abstract ParametersCompiled ParameterInfo { get ; }
  1979. public abstract TypeSpec ReturnType { get; }
  1980. #endregion
  1981. public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  1982. {
  1983. if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
  1984. Report.Error (1667, a.Location,
  1985. "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
  1986. a.Type.GetSignatureForError (), a.GetValidTargets ());
  1987. return;
  1988. }
  1989. if (a.IsValidSecurityAttribute ()) {
  1990. a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
  1991. return;
  1992. }
  1993. if (a.Target == AttributeTargets.Method) {
  1994. method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
  1995. return;
  1996. }
  1997. if (a.Target == AttributeTargets.ReturnValue) {
  1998. if (return_attributes == null)
  1999. return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
  2000. return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
  2001. return;
  2002. }
  2003. ApplyToExtraTarget (a, ctor, cdata, pa);
  2004. }
  2005. protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  2006. {
  2007. throw new NotSupportedException ("You forgot to define special attribute target handling");
  2008. }
  2009. // It is not supported for the accessors
  2010. public sealed override bool Define()
  2011. {
  2012. throw new NotSupportedException ();
  2013. }
  2014. public virtual void Emit (TypeDefinition parent)
  2015. {
  2016. method_data.Emit (parent);
  2017. if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
  2018. Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
  2019. if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
  2020. Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
  2021. if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  2022. return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
  2023. Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
  2024. } else if (ReturnType.HasDynamicElement) {
  2025. return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
  2026. Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
  2027. }
  2028. if (OptAttributes != null)
  2029. OptAttributes.Emit ();
  2030. if (declarative_security != null) {
  2031. foreach (var de in declarative_security) {
  2032. #if STATIC
  2033. method_data.MethodBuilder.__AddDeclarativeSecurity (de);
  2034. #else
  2035. method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
  2036. #endif
  2037. }
  2038. }
  2039. block = null;
  2040. }
  2041. public override bool EnableOverloadChecks (MemberCore overload)
  2042. {
  2043. if (overload is MethodCore) {
  2044. caching_flags |= Flags.MethodOverloadsExist;
  2045. return true;
  2046. }
  2047. // This can only happen with indexers and it will
  2048. // be catched as indexer difference
  2049. if (overload is AbstractPropertyEventMethod)
  2050. return true;
  2051. return false;
  2052. }
  2053. public override string GetCallerMemberName ()
  2054. {
  2055. return base.GetCallerMemberName ().Substring (prefix.Length);
  2056. }
  2057. public override string GetSignatureForDocumentation ()
  2058. {
  2059. // should not be called
  2060. throw new NotSupportedException ();
  2061. }
  2062. public override bool IsClsComplianceRequired()
  2063. {
  2064. return false;
  2065. }
  2066. public void PrepareEmit ()
  2067. {
  2068. method_data.DefineMethodBuilder (Parent.PartialContainer, ParameterInfo);
  2069. }
  2070. public override void WriteDebugSymbol (MonoSymbolFile file)
  2071. {
  2072. if (method_data != null)
  2073. method_data.WriteDebugSymbol (file);
  2074. }
  2075. public MethodSpec Spec { get; protected set; }
  2076. //
  2077. // Represents header string for documentation comment.
  2078. //
  2079. public override string DocCommentHeader {
  2080. get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
  2081. }
  2082. }
  2083. public class Operator : MethodOrOperator {
  2084. const Modifiers AllowedModifiers =
  2085. Modifiers.PUBLIC |
  2086. Modifiers.UNSAFE |
  2087. Modifiers.EXTERN |
  2088. Modifiers.STATIC;
  2089. public enum OpType : byte {
  2090. // Unary operators
  2091. LogicalNot,
  2092. OnesComplement,
  2093. Increment,
  2094. Decrement,
  2095. True,
  2096. False,
  2097. // Unary and Binary operators
  2098. Addition,
  2099. Subtraction,
  2100. UnaryPlus,
  2101. UnaryNegation,
  2102. // Binary operators
  2103. Multiply,
  2104. Division,
  2105. Modulus,
  2106. BitwiseAnd,
  2107. BitwiseOr,
  2108. ExclusiveOr,
  2109. LeftShift,
  2110. RightShift,
  2111. Equality,
  2112. Inequality,
  2113. GreaterThan,
  2114. LessThan,
  2115. GreaterThanOrEqual,
  2116. LessThanOrEqual,
  2117. // Implicit and Explicit
  2118. Implicit,
  2119. Explicit,
  2120. // Just because of enum
  2121. TOP
  2122. };
  2123. public readonly OpType OperatorType;
  2124. static readonly string [] [] names;
  2125. static Operator ()
  2126. {
  2127. names = new string[(int)OpType.TOP][];
  2128. names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
  2129. names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
  2130. names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
  2131. names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
  2132. names [(int) OpType.True] = new string [] { "true", "op_True" };
  2133. names [(int) OpType.False] = new string [] { "false", "op_False" };
  2134. names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
  2135. names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
  2136. names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
  2137. names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
  2138. names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
  2139. names [(int) OpType.Division] = new string [] { "/", "op_Division" };
  2140. names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
  2141. names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
  2142. names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
  2143. names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
  2144. names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
  2145. names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
  2146. names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
  2147. names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
  2148. names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
  2149. names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
  2150. names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
  2151. names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
  2152. names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
  2153. names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
  2154. }
  2155. public Operator (TypeDefinition parent, OpType type, FullNamedExpression ret_type, Modifiers mod_flags, ParametersCompiled parameters,
  2156. ToplevelBlock block, Attributes attrs, Location loc)
  2157. : base (parent, ret_type, mod_flags, AllowedModifiers, new MemberName (GetMetadataName (type), loc), attrs, parameters)
  2158. {
  2159. OperatorType = type;
  2160. Block = block;
  2161. }
  2162. public override void Accept (StructuralVisitor visitor)
  2163. {
  2164. visitor.Visit (this);
  2165. }
  2166. public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
  2167. {
  2168. if (a.Type == pa.Conditional) {
  2169. Error_ConditionalAttributeIsNotValid ();
  2170. return;
  2171. }
  2172. base.ApplyAttributeBuilder (a, ctor, cdata, pa);
  2173. }
  2174. public override bool Define ()
  2175. {
  2176. const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
  2177. if ((ModFlags & RequiredModifiers) != RequiredModifiers){
  2178. Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
  2179. }
  2180. if (!base.Define ())
  2181. return false;
  2182. if (block != null) {
  2183. if (block.IsIterator) {
  2184. //
  2185. // Current method is turned into automatically generated
  2186. // wrapper which creates an instance of iterator
  2187. //
  2188. Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
  2189. ModFlags |= Modifiers.DEBUGGER_HIDDEN;
  2190. }
  2191. if (Compiler.Settings.WriteMetadataOnly)
  2192. block = null;
  2193. }
  2194. // imlicit and explicit operator of same types are not allowed
  2195. if (OperatorType == OpType.Explicit)
  2196. Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
  2197. else if (OperatorType == OpType.Implicit)
  2198. Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
  2199. TypeSpec declaring_type = Parent.CurrentType;
  2200. TypeSpec return_type = MemberType;
  2201. TypeSpec first_arg_type = ParameterTypes [0];
  2202. TypeSpec first_arg_type_unwrap = first_arg_type;
  2203. if (first_arg_type.IsNullableType)
  2204. first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type);
  2205. TypeSpec return_type_unwrap = return_type;
  2206. if (return_type.IsNullableType)
  2207. return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type);
  2208. //
  2209. // Rules for conversion operators
  2210. //
  2211. if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
  2212. if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
  2213. Report.Error (555, Location,
  2214. "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
  2215. return false;
  2216. }
  2217. TypeSpec conv_type;
  2218. if (declaring_type == return_type || declaring_type == return_type_unwrap) {
  2219. conv_type = first_arg_type;
  2220. } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) {
  2221. conv_type = return_type;
  2222. } else {
  2223. Report.Error (556, Location,
  2224. "User-defined conversion must convert to or from the enclosing type");
  2225. return false;
  2226. }
  2227. if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  2228. Report.Error (1964, Location,
  2229. "User-defined conversion `{0}' cannot convert to or from the dynamic type",
  2230. GetSignatureForError ());
  2231. return false;
  2232. }
  2233. if (conv_type.IsInterface) {
  2234. Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
  2235. GetSignatureForError ());
  2236. return false;
  2237. }
  2238. if (conv_type.IsClass) {
  2239. if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) {
  2240. Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
  2241. GetSignatureForError ());
  2242. return false;
  2243. }
  2244. if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) {
  2245. Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
  2246. GetSignatureForError ());
  2247. return false;
  2248. }
  2249. }
  2250. } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
  2251. if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) {
  2252. 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");
  2253. return false;
  2254. }
  2255. } else if (parameters.Count == 1) {
  2256. // Checks for Unary operators
  2257. if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
  2258. if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) {
  2259. Report.Error (448, Location,
  2260. "The return type for ++ or -- operator must be the containing type or derived from the containing type");
  2261. return false;
  2262. }
  2263. if (first_arg_type != declaring_type) {
  2264. Report.Error (
  2265. 559, Location, "The parameter type for ++ or -- operator must be the containing type");
  2266. return false;
  2267. }
  2268. }
  2269. if (first_arg_type_unwrap != declaring_type) {
  2270. Report.Error (562, Location,
  2271. "The parameter type of a unary operator must be the containing type");
  2272. return false;
  2273. }
  2274. if (OperatorType == OpType.True || OperatorType == OpType.False) {
  2275. if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) {
  2276. Report.Error (
  2277. 215, Location,
  2278. "The return type of operator True or False " +
  2279. "must be bool");
  2280. return false;
  2281. }
  2282. }
  2283. } else if (first_arg_type_unwrap != declaring_type) {
  2284. // Checks for Binary operators
  2285. var second_arg_type = ParameterTypes[1];
  2286. if (second_arg_type.IsNullableType)
  2287. second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type);
  2288. if (second_arg_type != declaring_type) {
  2289. Report.Error (563, Location,
  2290. "One of the parameters of a binary operator must be the containing type");
  2291. return false;
  2292. }
  2293. }
  2294. return true;
  2295. }
  2296. protected override bool ResolveMemberType ()
  2297. {
  2298. if (!base.ResolveMemberType ())
  2299. return false;
  2300. flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
  2301. return true;
  2302. }
  2303. protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
  2304. {
  2305. // Operator cannot be override
  2306. bestCandidate = null;
  2307. return null;
  2308. }
  2309. public static string GetName (OpType ot)
  2310. {
  2311. return names [(int) ot] [0];
  2312. }
  2313. public static string GetName (string metadata_name)
  2314. {
  2315. for (int i = 0; i < names.Length; ++i) {
  2316. if (names [i] [1] == metadata_name)
  2317. return names [i] [0];
  2318. }
  2319. return null;
  2320. }
  2321. public static string GetMetadataName (OpType ot)
  2322. {
  2323. return names [(int) ot] [1];
  2324. }
  2325. public static string GetMetadataName (string name)
  2326. {
  2327. for (int i = 0; i < names.Length; ++i) {
  2328. if (names [i] [0] == name)
  2329. return names [i] [1];
  2330. }
  2331. return null;
  2332. }
  2333. public static OpType? GetType (string metadata_name)
  2334. {
  2335. for (int i = 0; i < names.Length; ++i) {
  2336. if (names[i][1] == metadata_name)
  2337. return (OpType) i;
  2338. }
  2339. return null;
  2340. }
  2341. public OpType GetMatchingOperator ()
  2342. {
  2343. switch (OperatorType) {
  2344. case OpType.Equality:
  2345. return OpType.Inequality;
  2346. case OpType.Inequality:
  2347. return OpType.Equality;
  2348. case OpType.True:
  2349. return OpType.False;
  2350. case OpType.False:
  2351. return OpType.True;
  2352. case OpType.GreaterThan:
  2353. return OpType.LessThan;
  2354. case OpType.LessThan:
  2355. return OpType.GreaterThan;
  2356. case OpType.GreaterThanOrEqual:
  2357. return OpType.LessThanOrEqual;
  2358. case OpType.LessThanOrEqual:
  2359. return OpType.GreaterThanOrEqual;
  2360. default:
  2361. return OpType.TOP;
  2362. }
  2363. }
  2364. public override string GetSignatureForDocumentation ()
  2365. {
  2366. string s = base.GetSignatureForDocumentation ();
  2367. if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
  2368. s = s + "~" + ReturnType.GetSignatureForDocumentation ();
  2369. }
  2370. return s;
  2371. }
  2372. public override string GetSignatureForError ()
  2373. {
  2374. StringBuilder sb = new StringBuilder ();
  2375. if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
  2376. sb.AppendFormat ("{0}.{1} operator {2}",
  2377. Parent.GetSignatureForError (), GetName (OperatorType),
  2378. member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ());
  2379. }
  2380. else {
  2381. sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
  2382. }
  2383. sb.Append (parameters.GetSignatureForError ());
  2384. return sb.ToString ();
  2385. }
  2386. }
  2387. }