cpp_overload_resolution.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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/expr_info.h"
  10. #include "toolchain/sem_ir/typed_insts.h"
  11. namespace Carbon::Check {
  12. // Invents a Clang argument expression to use in overload resolution to
  13. // represent the given Carbon argument instruction.
  14. static auto InventClangArg(Context& context, SemIR::InstId arg_id)
  15. -> clang::Expr* {
  16. clang::ExprValueKind value_kind;
  17. switch (SemIR::GetExprCategory(context.sem_ir(), arg_id)) {
  18. case SemIR::ExprCategory::NotExpr:
  19. CARBON_FATAL("Should not see these here");
  20. case SemIR::ExprCategory::Error:
  21. return nullptr;
  22. case SemIR::ExprCategory::DurableRef:
  23. value_kind = clang::ExprValueKind::VK_LValue;
  24. break;
  25. case SemIR::ExprCategory::EphemeralRef:
  26. value_kind = clang::ExprValueKind::VK_XValue;
  27. break;
  28. case SemIR::ExprCategory::Value:
  29. case SemIR::ExprCategory::Initializing:
  30. value_kind = clang::ExprValueKind::VK_PRValue;
  31. break;
  32. case SemIR::ExprCategory::Mixed:
  33. // TODO: Handle this by creating an InitListExpr.
  34. value_kind = clang::ExprValueKind::VK_PRValue;
  35. break;
  36. }
  37. if (context.insts().Get(arg_id).type_id() == SemIR::ErrorInst::TypeId) {
  38. // The argument error has already been diagnosed.
  39. return nullptr;
  40. }
  41. clang::QualType arg_cpp_type = MapToCppType(context, arg_id);
  42. if (arg_cpp_type.isNull()) {
  43. CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,
  44. "call argument of type {0} is not supported",
  45. TypeOfInstId);
  46. context.emitter().Emit(arg_id, CppCallArgTypeNotSupported, arg_id);
  47. return nullptr;
  48. }
  49. // TODO: Avoid heap allocating more of these on every call. Either cache them
  50. // somewhere or put them on the stack.
  51. return new (context.ast_context()) clang::OpaqueValueExpr(
  52. // TODO: Add location accordingly.
  53. clang::SourceLocation(), arg_cpp_type.getNonReferenceType(), value_kind);
  54. }
  55. // Adds the given overload candidates to the candidate set.
  56. static auto AddOverloadCandidataes(clang::Sema& sema,
  57. clang::OverloadCandidateSet& candidate_set,
  58. const clang::UnresolvedSetImpl& functions,
  59. clang::Expr* self_arg,
  60. llvm::ArrayRef<clang::Expr*> args) -> void {
  61. constexpr bool SuppressUserConversions = false;
  62. constexpr bool PartialOverloading = false;
  63. constexpr clang::TemplateArgumentListInfo* ExplicitTemplateArgs = nullptr;
  64. for (auto found_decl : functions.pairs()) {
  65. auto* decl = found_decl.getDecl()->getUnderlyingDecl();
  66. auto* template_decl = dyn_cast<clang::FunctionTemplateDecl>(decl);
  67. auto* fn_decl = template_decl ? template_decl->getTemplatedDecl()
  68. : cast<clang::FunctionDecl>(decl);
  69. auto* method_decl = dyn_cast<clang::CXXMethodDecl>(fn_decl);
  70. if (method_decl && !method_decl->isStatic() &&
  71. !isa<clang::CXXConstructorDecl>(fn_decl)) {
  72. clang::QualType self_type;
  73. clang::Expr::Classification self_classification;
  74. if (self_arg) {
  75. self_type = self_arg->getType();
  76. self_classification = self_arg->Classify(sema.Context);
  77. }
  78. if (template_decl) {
  79. sema.AddMethodTemplateCandidate(
  80. template_decl, found_decl,
  81. cast<clang::CXXRecordDecl>(template_decl->getDeclContext()),
  82. ExplicitTemplateArgs, self_type, self_classification, args,
  83. candidate_set, SuppressUserConversions, PartialOverloading);
  84. } else {
  85. sema.AddMethodCandidate(method_decl, found_decl,
  86. method_decl->getParent(), self_type,
  87. self_classification, args, candidate_set,
  88. SuppressUserConversions, PartialOverloading);
  89. }
  90. } else {
  91. if (template_decl) {
  92. sema.AddTemplateOverloadCandidate(
  93. template_decl, found_decl, ExplicitTemplateArgs, args,
  94. candidate_set, SuppressUserConversions, PartialOverloading);
  95. } else {
  96. sema.AddOverloadCandidate(fn_decl, found_decl, args, candidate_set,
  97. SuppressUserConversions, PartialOverloading);
  98. }
  99. }
  100. }
  101. }
  102. auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
  103. SemIR::CppOverloadSetId overload_set_id,
  104. SemIR::InstId self_id,
  105. llvm::ArrayRef<SemIR::InstId> arg_ids)
  106. -> SemIR::InstId {
  107. Diagnostics::AnnotationScope annotate_diagnostics(
  108. &context.emitter(), [&](auto& builder) {
  109. CARBON_DIAGNOSTIC(InCallToCppFunction, Note,
  110. "in call to Cpp function here");
  111. builder.Note(loc_id, InCallToCppFunction);
  112. });
  113. // Map Carbon call argument types to C++ types.
  114. clang::Expr* self_expr = nullptr;
  115. if (self_id.has_value()) {
  116. self_expr = InventClangArg(context, self_id);
  117. if (!self_expr) {
  118. return SemIR::ErrorInst::InstId;
  119. }
  120. }
  121. llvm::SmallVector<clang::Expr*> arg_exprs;
  122. arg_exprs.reserve(arg_ids.size());
  123. for (SemIR::InstId arg_id : arg_ids) {
  124. auto* arg_expr = InventClangArg(context, arg_id);
  125. if (!arg_expr) {
  126. return SemIR::ErrorInst::InstId;
  127. }
  128. arg_exprs.push_back(arg_expr);
  129. }
  130. const SemIR::CppOverloadSet& overload_set =
  131. context.cpp_overload_sets().Get(overload_set_id);
  132. // Add candidate functions from the name lookup.
  133. clang::OverloadCandidateSet candidate_set(
  134. // TODO: Add location accordingly.
  135. clang::SourceLocation(),
  136. clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal);
  137. clang::ASTUnit* ast = context.sem_ir().clang_ast_unit();
  138. CARBON_CHECK(ast);
  139. clang::Sema& sema = ast->getSema();
  140. AddOverloadCandidataes(sema, candidate_set, overload_set.candidate_functions,
  141. self_expr, arg_exprs);
  142. // Find best viable function among the candidates.
  143. clang::OverloadCandidateSet::iterator best_viable_fn;
  144. clang::OverloadingResult overloading_result =
  145. // TODO: Add location accordingly.
  146. candidate_set.BestViableFunction(sema, clang::SourceLocation(),
  147. best_viable_fn);
  148. switch (overloading_result) {
  149. case clang::OverloadingResult::OR_Success: {
  150. // TODO: Handle the cases when Function is null.
  151. CARBON_CHECK(best_viable_fn->Function);
  152. SemIR::InstId result =
  153. ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function);
  154. return result;
  155. }
  156. case clang::OverloadingResult::OR_No_Viable_Function: {
  157. // TODO: Add notes with the candidates.
  158. CARBON_DIAGNOSTIC(CppOverloadingNoViableFunctionFound, Error,
  159. "no matching function for call to `{0}`",
  160. SemIR::NameId);
  161. context.emitter().Emit(loc_id, CppOverloadingNoViableFunctionFound,
  162. overload_set.name_id);
  163. return SemIR::ErrorInst::InstId;
  164. }
  165. case clang::OverloadingResult::OR_Ambiguous: {
  166. // TODO: Add notes with the candidates.
  167. CARBON_DIAGNOSTIC(CppOverloadingAmbiguousCandidatesFound, Error,
  168. "call to `{0}` is ambiguous", SemIR::NameId);
  169. context.emitter().Emit(loc_id, CppOverloadingAmbiguousCandidatesFound,
  170. overload_set.name_id);
  171. return SemIR::ErrorInst::InstId;
  172. }
  173. case clang::OverloadingResult::OR_Deleted: {
  174. // TODO: Add notes with the candidates.
  175. CARBON_DIAGNOSTIC(CppOverloadingDeletedFunctionFound, Error,
  176. "call to deleted function `{0}`", SemIR::NameId);
  177. context.emitter().Emit(loc_id, CppOverloadingDeletedFunctionFound,
  178. overload_set.name_id);
  179. return SemIR::ErrorInst::InstId;
  180. }
  181. }
  182. }
  183. } // namespace Carbon::Check