cpp_overload_resolution.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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_type_mapping.h"
  8. #include "toolchain/check/import_cpp.h"
  9. namespace Carbon::Check {
  10. auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
  11. SemIR::InstId callee_id,
  12. llvm::ArrayRef<SemIR::InstId> arg_ids)
  13. -> std::optional<SemIR::InstId> {
  14. Diagnostics::AnnotationScope annotate_diagnostics(
  15. &context.emitter(), [&](auto& builder) {
  16. CARBON_DIAGNOSTIC(InCallToCppFunction, Note,
  17. "in call to Cpp function here");
  18. builder.Note(loc_id, InCallToCppFunction);
  19. });
  20. // Map Carbon call argument types to C++ types.
  21. llvm::SmallVector<clang::Expr*> arg_exprs;
  22. arg_exprs.reserve(arg_ids.size());
  23. for (SemIR::InstId arg_id : arg_ids) {
  24. clang::QualType arg_cpp_type = MapToCppType(context, arg_id);
  25. if (arg_cpp_type.isNull()) {
  26. CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,
  27. "call argument of type {0} is not supported",
  28. TypeOfInstId);
  29. context.emitter().Emit(loc_id, CppCallArgTypeNotSupported, arg_id);
  30. return std::nullopt;
  31. }
  32. // TODO: Allocate these on the stack.
  33. arg_exprs.emplace_back(new (context.ast_context()) clang::OpaqueValueExpr(
  34. // TODO: Add location accordingly.
  35. clang::SourceLocation(), arg_cpp_type.getNonReferenceType(),
  36. clang::ExprValueKind::VK_LValue));
  37. }
  38. auto overload_set_type =
  39. context.types()
  40. .GetAsInst(context.insts().Get(callee_id).type_id())
  41. .TryAs<SemIR::CppOverloadSetType>();
  42. // TODO: CHECK-fail or store CppOverloadSetId in the CalleeFunction and pass
  43. // it in here.
  44. if (!overload_set_type) {
  45. return std::nullopt;
  46. }
  47. const SemIR::CppOverloadSet& overload_set =
  48. context.cpp_overload_sets().Get(overload_set_type->overload_set_id);
  49. // Add candidate functions from the name lookup.
  50. clang::OverloadCandidateSet candidate_set(
  51. // TODO: Add location accordingly.
  52. clang::SourceLocation(),
  53. clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal);
  54. clang::ASTUnit* ast = context.sem_ir().clang_ast_unit();
  55. CARBON_CHECK(ast);
  56. clang::Sema& sema = ast->getSema();
  57. // TODO: Add support for method calls.
  58. for (clang::NamedDecl* candidate : overload_set.candidate_functions) {
  59. if (auto* fn_decl = dyn_cast<clang::FunctionDecl>(candidate)) {
  60. sema.AddOverloadCandidate(
  61. fn_decl, clang::DeclAccessPair::make(fn_decl, candidate->getAccess()),
  62. arg_exprs, candidate_set);
  63. } else if (isa<clang::FunctionTemplateDecl>(candidate)) {
  64. CARBON_DIAGNOSTIC(CppTemplateFunctionNotSupported, Error,
  65. "template function is not supported");
  66. context.emitter().Emit(loc_id, CppTemplateFunctionNotSupported);
  67. return std::nullopt;
  68. }
  69. // TODO: Diagnose if it's neither of these types.
  70. }
  71. // Find best viable function among the candidates.
  72. clang::OverloadCandidateSet::iterator best_viable_fn;
  73. clang::OverloadingResult overloading_result =
  74. // TODO: Add location accordingly.
  75. candidate_set.BestViableFunction(sema, clang::SourceLocation(),
  76. best_viable_fn);
  77. switch (overloading_result) {
  78. case clang::OverloadingResult::OR_Success: {
  79. // TODO: Handle the cases when Function is null.
  80. CARBON_CHECK(best_viable_fn->Function);
  81. SemIR::InstId result =
  82. ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function);
  83. return result;
  84. }
  85. case clang::OverloadingResult::OR_No_Viable_Function: {
  86. // TODO: Add notes with the candidates.
  87. CARBON_DIAGNOSTIC(CppOverloadingNoViableFunctionFound, Error,
  88. "no matching function for call to `{0}`",
  89. SemIR::NameId);
  90. context.emitter().Emit(loc_id, CppOverloadingNoViableFunctionFound,
  91. overload_set.name_id);
  92. return std::nullopt;
  93. }
  94. case clang::OverloadingResult::OR_Ambiguous: {
  95. // TODO: Add notes with the candidates.
  96. CARBON_DIAGNOSTIC(CppOverloadingAmbiguousCandidatesFound, Error,
  97. "call to `{0}` is ambiguous", SemIR::NameId);
  98. context.emitter().Emit(loc_id, CppOverloadingAmbiguousCandidatesFound,
  99. overload_set.name_id);
  100. return std::nullopt;
  101. }
  102. case clang::OverloadingResult::OR_Deleted: {
  103. // TODO: Add notes with the candidates.
  104. CARBON_DIAGNOSTIC(CppOverloadingDeletedFunctionFound, Error,
  105. "call to deleted function `{0}`", SemIR::NameId);
  106. context.emitter().Emit(loc_id, CppOverloadingDeletedFunctionFound,
  107. overload_set.name_id);
  108. return std::nullopt;
  109. }
  110. }
  111. }
  112. } // namespace Carbon::Check