cpp_overload_resolution.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. namespace Carbon::Check {
  10. auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
  11. SemIR::CppOverloadSetId overload_set_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. const SemIR::CppOverloadSet& overload_set =
  39. context.cpp_overload_sets().Get(overload_set_id);
  40. // Add candidate functions from the name lookup.
  41. clang::OverloadCandidateSet candidate_set(
  42. // TODO: Add location accordingly.
  43. clang::SourceLocation(),
  44. clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal);
  45. clang::ASTUnit* ast = context.sem_ir().clang_ast_unit();
  46. CARBON_CHECK(ast);
  47. clang::Sema& sema = ast->getSema();
  48. // TODO: Add support for method calls.
  49. for (clang::NamedDecl* candidate : overload_set.candidate_functions) {
  50. if (auto* fn_decl = dyn_cast<clang::FunctionDecl>(candidate)) {
  51. sema.AddOverloadCandidate(
  52. fn_decl, clang::DeclAccessPair::make(fn_decl, candidate->getAccess()),
  53. arg_exprs, candidate_set);
  54. } else if (isa<clang::FunctionTemplateDecl>(candidate)) {
  55. CARBON_DIAGNOSTIC(CppTemplateFunctionNotSupported, Error,
  56. "template function is not supported");
  57. context.emitter().Emit(loc_id, CppTemplateFunctionNotSupported);
  58. return std::nullopt;
  59. }
  60. // TODO: Diagnose if it's neither of these types.
  61. }
  62. // Find best viable function among the candidates.
  63. clang::OverloadCandidateSet::iterator best_viable_fn;
  64. clang::OverloadingResult overloading_result =
  65. // TODO: Add location accordingly.
  66. candidate_set.BestViableFunction(sema, clang::SourceLocation(),
  67. best_viable_fn);
  68. switch (overloading_result) {
  69. case clang::OverloadingResult::OR_Success: {
  70. // TODO: Handle the cases when Function is null.
  71. CARBON_CHECK(best_viable_fn->Function);
  72. SemIR::InstId result =
  73. ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function);
  74. return result;
  75. }
  76. case clang::OverloadingResult::OR_No_Viable_Function: {
  77. // TODO: Add notes with the candidates.
  78. CARBON_DIAGNOSTIC(CppOverloadingNoViableFunctionFound, Error,
  79. "no matching function for call to `{0}`",
  80. SemIR::NameId);
  81. context.emitter().Emit(loc_id, CppOverloadingNoViableFunctionFound,
  82. overload_set.name_id);
  83. return std::nullopt;
  84. }
  85. case clang::OverloadingResult::OR_Ambiguous: {
  86. // TODO: Add notes with the candidates.
  87. CARBON_DIAGNOSTIC(CppOverloadingAmbiguousCandidatesFound, Error,
  88. "call to `{0}` is ambiguous", SemIR::NameId);
  89. context.emitter().Emit(loc_id, CppOverloadingAmbiguousCandidatesFound,
  90. overload_set.name_id);
  91. return std::nullopt;
  92. }
  93. case clang::OverloadingResult::OR_Deleted: {
  94. // TODO: Add notes with the candidates.
  95. CARBON_DIAGNOSTIC(CppOverloadingDeletedFunctionFound, Error,
  96. "call to deleted function `{0}`", SemIR::NameId);
  97. context.emitter().Emit(loc_id, CppOverloadingDeletedFunctionFound,
  98. overload_set.name_id);
  99. return std::nullopt;
  100. }
  101. }
  102. }
  103. } // namespace Carbon::Check