public static void Reset () { usage_attr_cache = new PtrHashtable (); att_cache = new PtrHashtable (); }
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 (); }
/// <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; }