diagnostic_loc_converter.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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/sem_ir/diagnostic_loc_converter.h"
  5. namespace Carbon::SemIR {
  6. auto DiagnosticLocConverter::ConvertWithImports(LocId loc_id,
  7. bool token_only) const
  8. -> LocAndImports {
  9. llvm::SmallVector<SemIR::AbsoluteNodeId> absolute_node_ids =
  10. SemIR::GetAbsoluteNodeId(sem_ir_, loc_id);
  11. auto final_node_id = absolute_node_ids.pop_back_val();
  12. // Convert the final location.
  13. LocAndImports result = {.loc = ConvertImpl(final_node_id, token_only)};
  14. // Convert the import locations.
  15. for (const auto& absolute_node_id : absolute_node_ids) {
  16. if (!absolute_node_id.node_id().has_value()) {
  17. // TODO: Add an `ImportLoc` pointing at the prelude for the case where
  18. // we don't have a location.
  19. continue;
  20. }
  21. result.imports.push_back({.loc = ConvertImpl(absolute_node_id, false).loc});
  22. }
  23. return result;
  24. }
  25. auto DiagnosticLocConverter::Convert(LocId loc_id, bool token_only) const
  26. -> Diagnostics::ConvertedLoc {
  27. llvm::SmallVector<SemIR::AbsoluteNodeId> absolute_node_ids =
  28. SemIR::GetAbsoluteNodeId(sem_ir_, loc_id);
  29. return ConvertImpl(absolute_node_ids.back(), token_only);
  30. }
  31. auto DiagnosticLocConverter::ConvertImpl(SemIR::AbsoluteNodeId absolute_node_id,
  32. bool token_only) const
  33. -> Diagnostics::ConvertedLoc {
  34. if (absolute_node_id.check_ir_id() == SemIR::CheckIRId::Cpp) {
  35. return ConvertImpl(absolute_node_id.clang_source_loc_id());
  36. }
  37. return ConvertImpl(absolute_node_id.check_ir_id(), absolute_node_id.node_id(),
  38. token_only);
  39. }
  40. auto DiagnosticLocConverter::ConvertImpl(SemIR::CheckIRId check_ir_id,
  41. Parse::NodeId node_id,
  42. bool token_only) const
  43. -> Diagnostics::ConvertedLoc {
  44. CARBON_CHECK(check_ir_id != SemIR::CheckIRId::Cpp);
  45. const auto& tree_and_subtrees =
  46. tree_and_subtrees_getters_->Get(check_ir_id)();
  47. return tree_and_subtrees.NodeToDiagnosticLoc(node_id, token_only);
  48. }
  49. auto DiagnosticLocConverter::ConvertImpl(
  50. ClangSourceLocId clang_source_loc_id) const -> Diagnostics::ConvertedLoc {
  51. clang::SourceLocation clang_loc =
  52. sem_ir_->clang_source_locs().Get(clang_source_loc_id);
  53. CARBON_CHECK(sem_ir_->cpp_ast());
  54. clang::PresumedLoc presumed_loc =
  55. sem_ir_->cpp_ast()->getSourceManager().getPresumedLoc(clang_loc);
  56. if (presumed_loc.isInvalid()) {
  57. return Diagnostics::ConvertedLoc();
  58. }
  59. unsigned offset =
  60. sem_ir_->cpp_ast()->getSourceManager().getDecomposedLoc(clang_loc).second;
  61. return Diagnostics::ConvertedLoc{
  62. .loc = {.filename = presumed_loc.getFilename(),
  63. .line_number = static_cast<int32_t>(presumed_loc.getLine())},
  64. .last_byte_offset = static_cast<int32_t>(offset)};
  65. }
  66. } // namespace Carbon::SemIR