overload_resolution.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/check/cpp/overload_resolution.h"
  5. #include "clang/Basic/DiagnosticSema.h"
  6. #include "clang/Sema/Overload.h"
  7. #include "clang/Sema/Sema.h"
  8. #include "toolchain/base/kind_switch.h"
  9. #include "toolchain/check/cpp/import.h"
  10. #include "toolchain/check/cpp/location.h"
  11. #include "toolchain/check/cpp/type_mapping.h"
  12. #include "toolchain/diagnostics/diagnostic_emitter.h"
  13. #include "toolchain/sem_ir/function.h"
  14. #include "toolchain/sem_ir/ids.h"
  15. #include "toolchain/sem_ir/typed_insts.h"
  16. namespace Carbon::Check {
  17. // Map a Carbon name into a C++ name.
  18. static auto GetCppName(Context& context, SemIR::NameId name_id)
  19. -> clang::DeclarationName {
  20. // TODO: Some special names should probably use different formatting. In
  21. // particular, NameId::CppOperator should probably map back to a
  22. // CXXOperatorName.
  23. auto name_str = context.names().GetFormatted(name_id);
  24. return clang::DeclarationName(&context.ast_context().Idents.get(name_str));
  25. }
  26. // Adds the given overload candidates to the candidate set.
  27. static auto AddOverloadCandidataes(clang::Sema& sema,
  28. clang::OverloadCandidateSet& candidate_set,
  29. const clang::UnresolvedSetImpl& functions,
  30. clang::Expr* self_arg,
  31. llvm::ArrayRef<clang::Expr*> args) -> void {
  32. constexpr bool SuppressUserConversions = false;
  33. constexpr bool PartialOverloading = false;
  34. constexpr clang::TemplateArgumentListInfo* ExplicitTemplateArgs = nullptr;
  35. for (auto found_decl : functions.pairs()) {
  36. auto* decl = found_decl.getDecl()->getUnderlyingDecl();
  37. auto* template_decl = dyn_cast<clang::FunctionTemplateDecl>(decl);
  38. auto* fn_decl = template_decl ? template_decl->getTemplatedDecl()
  39. : cast<clang::FunctionDecl>(decl);
  40. auto* method_decl = dyn_cast<clang::CXXMethodDecl>(fn_decl);
  41. if (method_decl && !method_decl->isStatic() &&
  42. !isa<clang::CXXConstructorDecl>(fn_decl)) {
  43. clang::QualType self_type;
  44. clang::Expr::Classification self_classification;
  45. if (self_arg) {
  46. self_type = self_arg->getType();
  47. self_classification = self_arg->Classify(sema.Context);
  48. }
  49. if (template_decl) {
  50. sema.AddMethodTemplateCandidate(
  51. template_decl, found_decl,
  52. cast<clang::CXXRecordDecl>(template_decl->getDeclContext()),
  53. ExplicitTemplateArgs, self_type, self_classification, args,
  54. candidate_set, SuppressUserConversions, PartialOverloading);
  55. } else if (method_decl->isOverloadedOperator()) {
  56. sema.AddMemberOperatorCandidates(method_decl->getOverloadedOperator(),
  57. candidate_set.getLocation(), args,
  58. candidate_set);
  59. } else {
  60. sema.AddMethodCandidate(method_decl, found_decl,
  61. method_decl->getParent(), self_type,
  62. self_classification, args, candidate_set,
  63. SuppressUserConversions, PartialOverloading);
  64. }
  65. } else if (template_decl) {
  66. sema.AddTemplateOverloadCandidate(
  67. template_decl, found_decl, ExplicitTemplateArgs, args, candidate_set,
  68. SuppressUserConversions, PartialOverloading);
  69. } else {
  70. sema.AddOverloadCandidate(fn_decl, found_decl, args, candidate_set,
  71. SuppressUserConversions, PartialOverloading);
  72. }
  73. }
  74. }
  75. // Returns whether the decl is an operator member function.
  76. static auto IsOperatorMethodDecl(clang::Decl* decl) -> bool {
  77. auto* clang_method_decl = dyn_cast<clang::CXXMethodDecl>(decl);
  78. return clang_method_decl && clang_method_decl->isOverloadedOperator();
  79. }
  80. // Resolve which function to call, or returns an error instruction if overload
  81. // resolution failed.
  82. static auto ResolveCalleeId(Context& context, SemIR::LocId loc_id,
  83. SemIR::CppOverloadSetId overload_set_id,
  84. SemIR::InstId self_id,
  85. llvm::ArrayRef<SemIR::InstId> arg_ids)
  86. -> SemIR::InstId {
  87. // Register an annotation scope to flush any Clang diagnostics when we return.
  88. // This is important to ensure that Clang diagnostics are properly interleaved
  89. // with Carbon diagnostics.
  90. Diagnostics::AnnotationScope annotate_diagnostics(&context.emitter(),
  91. [](auto& /*builder*/) {});
  92. // Map Carbon call argument types to C++ types.
  93. clang::Expr* self_expr = nullptr;
  94. if (self_id.has_value()) {
  95. self_expr = InventClangArg(context, self_id);
  96. if (!self_expr) {
  97. return SemIR::ErrorInst::InstId;
  98. }
  99. }
  100. auto maybe_arg_exprs = InventClangArgs(context, arg_ids);
  101. if (!maybe_arg_exprs.has_value()) {
  102. return SemIR::ErrorInst::InstId;
  103. }
  104. auto& arg_exprs = *maybe_arg_exprs;
  105. const SemIR::CppOverloadSet& overload_set =
  106. context.cpp_overload_sets().Get(overload_set_id);
  107. clang::SourceLocation loc = GetCppLocation(context, loc_id);
  108. // Add candidate functions from the name lookup.
  109. clang::OverloadCandidateSet candidate_set(
  110. loc, clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal);
  111. clang::Sema& sema = context.clang_sema();
  112. AddOverloadCandidataes(sema, candidate_set, overload_set.candidate_functions,
  113. self_expr, arg_exprs);
  114. // Find best viable function among the candidates.
  115. clang::OverloadCandidateSet::iterator best_viable_fn;
  116. clang::OverloadingResult overloading_result =
  117. candidate_set.BestViableFunction(sema, loc, best_viable_fn);
  118. switch (overloading_result) {
  119. case clang::OverloadingResult::OR_Success: {
  120. // TODO: Handle the cases when Function is null.
  121. CARBON_CHECK(best_viable_fn->Function);
  122. sema.MarkFunctionReferenced(loc, best_viable_fn->Function);
  123. SemIR::InstId result = ImportCppFunctionDecl(
  124. context, loc_id, best_viable_fn->Function,
  125. // If this is an operator method, the first arg will be used as self.
  126. arg_exprs.size() -
  127. (IsOperatorMethodDecl(best_viable_fn->Function) ? 1 : 0));
  128. return result;
  129. }
  130. case clang::OverloadingResult::OR_No_Viable_Function: {
  131. candidate_set.NoteCandidates(
  132. clang::PartialDiagnosticAt(
  133. loc, sema.PDiag(clang::diag::err_ovl_no_viable_function_in_call)
  134. << GetCppName(context, overload_set.name_id)),
  135. sema, clang::OCD_AllCandidates, arg_exprs);
  136. return SemIR::ErrorInst::InstId;
  137. }
  138. case clang::OverloadingResult::OR_Ambiguous: {
  139. candidate_set.NoteCandidates(
  140. clang::PartialDiagnosticAt(
  141. loc, sema.PDiag(clang::diag::err_ovl_ambiguous_call)
  142. << GetCppName(context, overload_set.name_id)),
  143. sema, clang::OCD_AmbiguousCandidates, arg_exprs);
  144. return SemIR::ErrorInst::InstId;
  145. }
  146. case clang::OverloadingResult::OR_Deleted: {
  147. sema.DiagnoseUseOfDeletedFunction(
  148. loc, clang::SourceRange(loc, loc),
  149. GetCppName(context, overload_set.name_id), candidate_set,
  150. best_viable_fn->Function, arg_exprs);
  151. return SemIR::ErrorInst::InstId;
  152. }
  153. }
  154. }
  155. // Returns whether the function is an imported C++ operator member function.
  156. static auto IsCppOperatorMethod(Context& context, SemIR::FunctionId function_id)
  157. -> bool {
  158. SemIR::ClangDeclId clang_decl_id =
  159. context.functions().Get(function_id).clang_decl_id;
  160. return clang_decl_id.has_value() &&
  161. IsOperatorMethodDecl(
  162. context.clang_decls().Get(clang_decl_id).key.decl);
  163. }
  164. auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
  165. SemIR::CppOverloadSetId overload_set_id,
  166. SemIR::InstId self_id,
  167. llvm::ArrayRef<SemIR::InstId> arg_ids)
  168. -> CppOverloadResolutionResult {
  169. CppOverloadResolutionResult result = {
  170. .callee_id =
  171. ResolveCalleeId(context, loc_id, overload_set_id, self_id, arg_ids),
  172. .arg_ids = arg_ids};
  173. SemIR::Callee callee = GetCallee(context.sem_ir(), result.callee_id);
  174. CARBON_KIND_SWITCH(callee) {
  175. case CARBON_KIND(SemIR::CalleeError _): {
  176. result.callee_id = SemIR::ErrorInst::InstId;
  177. return result;
  178. }
  179. case CARBON_KIND(SemIR::CalleeFunction fn): {
  180. CARBON_CHECK(!fn.self_id.has_value());
  181. if (self_id.has_value()) {
  182. // Preserve the `self` argument from the original callee.
  183. fn.self_id = self_id;
  184. } else if (IsCppOperatorMethod(context, fn.function_id)) {
  185. // Adjust `self` and args for C++ overloaded operator methods.
  186. fn.self_id = result.arg_ids.consume_front();
  187. }
  188. result.callee_function = fn;
  189. return result;
  190. }
  191. case CARBON_KIND(SemIR::CalleeCppOverloadSet _): {
  192. CARBON_FATAL("overloads can't be recursive");
  193. }
  194. case CARBON_KIND(SemIR::CalleeNonFunction _): {
  195. CARBON_FATAL("overloads should produce functions");
  196. }
  197. }
  198. }
  199. } // namespace Carbon::Check