Example #1
0
		public static void Reset ()
		{
			usage_attr_cache = new PtrHashtable ();
			att_cache = new PtrHashtable ();
		}
Example #2
0
		public static void Reset ()
		{
			analyzed_types = new PtrHashtable ();
			analyzed_types_obsolete = new PtrHashtable ();
			analyzed_member_obsolete = new PtrHashtable ();
			analyzed_method_excluded = new PtrHashtable ();
			fixed_buffer_cache = new PtrHashtable ();
		}
Example #3
0
		/// <summary>
		///   Find the Applicable Function Members (7.4.2.1)
		///
		///   me: Method Group expression with the members to select.
		///       it might contain constructors or methods (or anything
		///       that maps to a method).
		///
		///   Arguments: ArrayList containing resolved Argument objects.
		///
		///   loc: The location if we want an error to be reported, or a Null
		///        location for "probing" purposes.
		///
		///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
		///            that is the best match of me on Arguments.
		///
		/// </summary>
		public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList Arguments,
			bool may_fail, Location loc)
		{
			bool method_params = false;
			Type applicable_type = null;
			int arg_count = 0;
			ArrayList candidates = new ArrayList (2);
			ArrayList candidate_overrides = null;

			//
			// Used to keep a map between the candidate
			// and whether it is being considered in its
			// normal or expanded form
			//
			// false is normal form, true is expanded form
			//
			Hashtable candidate_to_form = null;

			if (Arguments != null)
				arg_count = Arguments.Count;

			if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
				if (!may_fail)
					Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
				return null;
			}

			int nmethods = Methods.Length;

			if (!IsBase) {
				//
				// Methods marked 'override' don't take part in 'applicable_type'
				// computation, nor in the actual overload resolution.
				// However, they still need to be emitted instead of a base virtual method.
				// So, we salt them away into the 'candidate_overrides' array.
				//
				// In case of reflected methods, we replace each overriding method with
				// its corresponding base virtual method.  This is to improve compatibility
				// with non-C# libraries which change the visibility of overrides (#75636)
				//
				int j = 0;
				for (int i = 0; i < Methods.Length; ++i) {
					MethodBase m = Methods [i];
					if (TypeManager.IsOverride (m)) {
						if (candidate_overrides == null)
							candidate_overrides = new ArrayList ();
						candidate_overrides.Add (m);
						m = TypeManager.TryGetBaseDefinition (m);
					}
					if (m != null)
						Methods [j++] = m;
				}
				nmethods = j;
			}

			//
			// Enable message recording, it's used mainly by lambda expressions
			//
			Report.IMessageRecorder msg_recorder = new Report.MessageRecorder ();
			Report.IMessageRecorder prev_recorder = Report.SetMessageRecorder (msg_recorder);

			//
			// First we construct the set of applicable methods
			//
			bool is_sorted = true;
			int best_candidate_rate = int.MaxValue;
			for (int i = 0; i < nmethods; i++) {
				Type decl_type = Methods [i].DeclaringType;

				//
				// If we have already found an applicable method
				// we eliminate all base types (Section 14.5.5.1)
				//
				if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
					continue;

				//
				// Check if candidate is applicable (section 14.4.2.1)
				//
				bool params_expanded_form = false;
				int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i], ref params_expanded_form);

				if (candidate_rate < best_candidate_rate) {
					best_candidate_rate = candidate_rate;
					best_candidate = Methods [i];
				}
				
				if (params_expanded_form) {
					if (candidate_to_form == null)
						candidate_to_form = new PtrHashtable ();
					MethodBase candidate = Methods [i];
					candidate_to_form [candidate] = candidate;
				}

				if (candidate_rate != 0 || has_inaccessible_candidates_only) {
					if (msg_recorder != null)
						msg_recorder.EndSession ();
					continue;
				}

				msg_recorder = null;
				candidates.Add (Methods [i]);

				if (applicable_type == null)
					applicable_type = decl_type;
				else if (applicable_type != decl_type) {
					is_sorted = false;
					if (IsAncestralType (applicable_type, decl_type))
						applicable_type = decl_type;
				}
			}

			Report.SetMessageRecorder (prev_recorder);
			if (msg_recorder != null && !msg_recorder.IsEmpty) {
				if (!may_fail)
					msg_recorder.PrintMessages ();

				return null;
			}
			
			int candidate_top = candidates.Count;

			if (applicable_type == null) {
				//
				// When we found a top level method which does not match and it's 
				// not an extension method. We start extension methods lookup from here
				//
				if (InstanceExpression != null) {
					ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name, loc);
					if (ex_method_lookup != null) {
						ex_method_lookup.ExtensionExpression = InstanceExpression;
						ex_method_lookup.SetTypeArguments (type_arguments);
						return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
					}
				}
				
				if (may_fail)
					return null;

				//
				// Okay so we have failed to find exact match so we
				// return error info about the closest match
				//
				if (best_candidate != null) {
					if (CustomErrorHandler != null && CustomErrorHandler.NoExactMatch (ec, best_candidate))
						return null;

					AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
					bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
					if (arg_count == pd.Count || pd.HasParams) {
						if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
							if (type_arguments == null) {
								Report.Error (411, loc,
									"The type arguments for method `{0}' cannot be inferred from " +
									"the usage. Try specifying the type arguments explicitly",
									TypeManager.CSharpSignature (best_candidate));
								return null;
							}

							Type[] g_args = TypeManager.GetGenericArguments (best_candidate);
							if (type_arguments.Count != g_args.Length) {
								Report.SymbolRelatedToPreviousError (best_candidate);
								Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
									TypeManager.CSharpSignature (best_candidate),
									g_args.Length.ToString ());
								return null;
							}
						} else {
							if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
								Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
								return null;
							}
						}

						if (has_inaccessible_candidates_only) {
							if (InstanceExpression != null && type != ec.ContainerType && TypeManager.IsNestedFamilyAccessible (ec.ContainerType, best_candidate.DeclaringType)) {
								// Although a derived class can access protected members of
								// its base class it cannot do so through an instance of the
								// base class (CS1540).  If the qualifier_type is a base of the
								// ec.ContainerType and the lookup succeeds with the latter one,
								// then we are in this situation.
								Error_CannotAccessProtected (loc, best_candidate, type, ec.ContainerType);
							} else {
								Report.SymbolRelatedToPreviousError (best_candidate);
								ErrorIsInaccesible (loc, GetSignatureForError ());
							}
						}

						if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
							return null;

						if (has_inaccessible_candidates_only)
							return null;

						throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate);
					}
				}

				//
				// We failed to find any method with correct argument count
				//
				if (Name == ConstructorInfo.ConstructorName) {
					Report.SymbolRelatedToPreviousError (type);
					Report.Error (1729, loc,
						"The type `{0}' does not contain a constructor that takes `{1}' arguments",
						TypeManager.CSharpName (type), arg_count);
				} else {
					Error_ArgumentCountWrong (arg_count);
				}
                                
				return null;
			}

			if (!is_sorted) {
				//
				// At this point, applicable_type is _one_ of the most derived types
				// in the set of types containing the methods in this MethodGroup.
				// Filter the candidates so that they only contain methods from the
				// most derived types.
				//

				int finalized = 0; // Number of finalized candidates

				do {
					// Invariant: applicable_type is a most derived type
					
					// We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
					// eliminating all it's base types.  At the same time, we'll also move
					// every unrelated type to the end of the array, and pick the next
					// 'applicable_type'.

					Type next_applicable_type = null;
					int j = finalized; // where to put the next finalized candidate
					int k = finalized; // where to put the next undiscarded candidate
					for (int i = finalized; i < candidate_top; ++i) {
						MethodBase candidate = (MethodBase) candidates [i];
						Type decl_type = candidate.DeclaringType;

						if (decl_type == applicable_type) {
							candidates [k++] = candidates [j];
							candidates [j++] = candidates [i];
							continue;
						}

						if (IsAncestralType (decl_type, applicable_type))
							continue;

						if (next_applicable_type != null &&
							IsAncestralType (decl_type, next_applicable_type))
							continue;

						candidates [k++] = candidates [i];

						if (next_applicable_type == null ||
							IsAncestralType (next_applicable_type, decl_type))
							next_applicable_type = decl_type;
					}

					applicable_type = next_applicable_type;
					finalized = j;
					candidate_top = k;
				} while (applicable_type != null);
			}

			//
			// Now we actually find the best method
			//

			best_candidate = (MethodBase) candidates [0];
			method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);

			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);

				if (BetterFunction (ec, Arguments, arg_count, 
					candidate, cand_params,
					best_candidate, method_params)) {
					best_candidate = candidate;
					method_params = cand_params;
				}
			}
			//
			// Now check that there are no ambiguities i.e the selected method
			// should be better than all the others
			//
			MethodBase ambiguous = null;
			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
				if (!BetterFunction (ec, Arguments, arg_count,
					best_candidate, method_params,
					candidate, cand_params)) 
				{
					if (!may_fail)
						Report.SymbolRelatedToPreviousError (candidate);
					ambiguous = candidate;
				}
			}

			if (ambiguous != null) {
				Error_AmbiguousCall (ambiguous);
				return this;
			}

			//
			// If the method is a virtual function, pick an override closer to the LHS type.
			//
			if (!IsBase && best_candidate.IsVirtual) {
				if (TypeManager.IsOverride (best_candidate))
					throw new InternalErrorException (
						"Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);

				if (candidate_overrides != null) {
					Type[] gen_args = null;
					bool gen_override = false;
					if (TypeManager.IsGenericMethod (best_candidate))
						gen_args = TypeManager.GetGenericArguments (best_candidate);

					foreach (MethodBase candidate in candidate_overrides) {
						if (TypeManager.IsGenericMethod (candidate)) {
							if (gen_args == null)
								continue;

							if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
								continue;
						} else {
							if (gen_args != null)
								continue;
						}
						
						if (IsOverride (candidate, best_candidate)) {
							gen_override = true;
							best_candidate = candidate;
						}
					}

					if (gen_override && gen_args != null) {
#if GMCS_SOURCE
						best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
#endif						
					}
				}
			}

			//
			// And now check if the arguments are all
			// compatible, perform conversions if
			// necessary etc. and return if everything is
			// all right
			//
			if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate,
				method_params, may_fail, loc))
				return null;

			if (best_candidate == null)
				return null;

			MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
#if GMCS_SOURCE
			if (the_method.IsGenericMethodDefinition &&
			    !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
				return null;
#endif

			//
			// Check ObsoleteAttribute on the best method
			//
			ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method);
			if (oa != null && !ec.IsInObsoleteScope)
				AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc);

			IMethodData data = TypeManager.GetMethod (the_method);
			if (data != null)
				data.SetMemberIsUsed ();

			return this;
		}