overload_resolution.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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/Sema/Overload.h"
  6. #include "clang/Sema/Sema.h"
  7. #include "toolchain/check/cpp/import.h"
  8. #include "toolchain/check/cpp/type_mapping.h"
  9. #include "toolchain/sem_ir/ids.h"
  10. #include "toolchain/sem_ir/typed_insts.h"
  11. namespace Carbon::Check {
  12. // Adds the given overload candidates to the candidate set.
  13. static auto AddOverloadCandidataes(clang::Sema& sema,
  14. clang::OverloadCandidateSet& candidate_set,
  15. const clang::UnresolvedSetImpl& functions,
  16. clang::Expr* self_arg,
  17. llvm::ArrayRef<clang::Expr*> args) -> void {
  18. constexpr bool SuppressUserConversions = false;
  19. constexpr bool PartialOverloading = false;
  20. constexpr clang::TemplateArgumentListInfo* ExplicitTemplateArgs = nullptr;
  21. for (auto found_decl : functions.pairs()) {
  22. auto* decl = found_decl.getDecl()->getUnderlyingDecl();
  23. auto* template_decl = dyn_cast<clang::FunctionTemplateDecl>(decl);
  24. auto* fn_decl = template_decl ? template_decl->getTemplatedDecl()
  25. : cast<clang::FunctionDecl>(decl);
  26. auto* method_decl = dyn_cast<clang::CXXMethodDecl>(fn_decl);
  27. if (method_decl && !method_decl->isStatic() &&
  28. !isa<clang::CXXConstructorDecl>(fn_decl)) {
  29. clang::QualType self_type;
  30. clang::Expr::Classification self_classification;
  31. if (self_arg) {
  32. self_type = self_arg->getType();
  33. self_classification = self_arg->Classify(sema.Context);
  34. }
  35. if (template_decl) {
  36. sema.AddMethodTemplateCandidate(
  37. template_decl, found_decl,
  38. cast<clang::CXXRecordDecl>(template_decl->getDeclContext()),
  39. ExplicitTemplateArgs, self_type, self_classification, args,
  40. candidate_set, SuppressUserConversions, PartialOverloading);
  41. } else {
  42. sema.AddMethodCandidate(method_decl, found_decl,
  43. method_decl->getParent(), self_type,
  44. self_classification, args, candidate_set,
  45. SuppressUserConversions, PartialOverloading);
  46. }
  47. } else {
  48. if (template_decl) {
  49. sema.AddTemplateOverloadCandidate(
  50. template_decl, found_decl, ExplicitTemplateArgs, args,
  51. candidate_set, SuppressUserConversions, PartialOverloading);
  52. } else {
  53. sema.AddOverloadCandidate(fn_decl, found_decl, args, candidate_set,
  54. SuppressUserConversions, PartialOverloading);
  55. }
  56. }
  57. }
  58. }
  59. auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
  60. SemIR::CppOverloadSetId overload_set_id,
  61. SemIR::InstId self_id,
  62. llvm::ArrayRef<SemIR::InstId> arg_ids)
  63. -> SemIR::InstId {
  64. Diagnostics::AnnotationScope annotate_diagnostics(
  65. &context.emitter(), [&](auto& builder) {
  66. CARBON_DIAGNOSTIC(InCallToCppFunction, Note,
  67. "in call to Cpp function here");
  68. builder.Note(loc_id, InCallToCppFunction);
  69. });
  70. // Map Carbon call argument types to C++ types.
  71. clang::Expr* self_expr = nullptr;
  72. if (self_id.has_value()) {
  73. self_expr = InventClangArg(context, self_id);
  74. if (!self_expr) {
  75. return SemIR::ErrorInst::InstId;
  76. }
  77. }
  78. auto arg_exprs = InventClangArgs(context, arg_ids);
  79. if (!arg_exprs.has_value()) {
  80. return SemIR::ErrorInst::InstId;
  81. }
  82. const SemIR::CppOverloadSet& overload_set =
  83. context.cpp_overload_sets().Get(overload_set_id);
  84. // Add candidate functions from the name lookup.
  85. clang::OverloadCandidateSet candidate_set(
  86. // TODO: Add location accordingly.
  87. clang::SourceLocation(),
  88. clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal);
  89. clang::ASTUnit* ast = context.sem_ir().clang_ast_unit();
  90. CARBON_CHECK(ast);
  91. clang::Sema& sema = ast->getSema();
  92. AddOverloadCandidataes(sema, candidate_set, overload_set.candidate_functions,
  93. self_expr, *arg_exprs);
  94. // Find best viable function among the candidates.
  95. clang::OverloadCandidateSet::iterator best_viable_fn;
  96. clang::OverloadingResult overloading_result =
  97. // TODO: Add location accordingly.
  98. candidate_set.BestViableFunction(sema, clang::SourceLocation(),
  99. best_viable_fn);
  100. switch (overloading_result) {
  101. case clang::OverloadingResult::OR_Success: {
  102. // TODO: Handle the cases when Function is null.
  103. CARBON_CHECK(best_viable_fn->Function);
  104. sema.MarkFunctionReferenced(clang::SourceLocation(),
  105. best_viable_fn->Function);
  106. SemIR::InstId result =
  107. ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function);
  108. return result;
  109. }
  110. case clang::OverloadingResult::OR_No_Viable_Function: {
  111. // TODO: Add notes with the candidates.
  112. CARBON_DIAGNOSTIC(CppOverloadingNoViableFunctionFound, Error,
  113. "no matching function for call to `{0}`",
  114. SemIR::NameId);
  115. context.emitter().Emit(loc_id, CppOverloadingNoViableFunctionFound,
  116. overload_set.name_id);
  117. return SemIR::ErrorInst::InstId;
  118. }
  119. case clang::OverloadingResult::OR_Ambiguous: {
  120. // TODO: Add notes with the candidates.
  121. CARBON_DIAGNOSTIC(CppOverloadingAmbiguousCandidatesFound, Error,
  122. "call to `{0}` is ambiguous", SemIR::NameId);
  123. context.emitter().Emit(loc_id, CppOverloadingAmbiguousCandidatesFound,
  124. overload_set.name_id);
  125. return SemIR::ErrorInst::InstId;
  126. }
  127. case clang::OverloadingResult::OR_Deleted: {
  128. // TODO: Add notes with the candidates.
  129. CARBON_DIAGNOSTIC(CppOverloadingDeletedFunctionFound, Error,
  130. "call to deleted function `{0}`", SemIR::NameId);
  131. context.emitter().Emit(loc_id, CppOverloadingDeletedFunctionFound,
  132. overload_set.name_id);
  133. return SemIR::ErrorInst::InstId;
  134. }
  135. }
  136. }
  137. } // namespace Carbon::Check