merge.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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/merge.h"
  5. #include "toolchain/check/function.h"
  6. #include "toolchain/check/import_ref.h"
  7. namespace Carbon::Check {
  8. // Returns the instruction to consider when merging the given inst_id. Returns
  9. // nullopt if merging is infeasible and no diagnostic should be printed.
  10. static auto ResolveMergeableInst(Context& context, SemIR::InstId inst_id)
  11. -> std::optional<SemIR::Inst> {
  12. auto inst = context.insts().Get(inst_id);
  13. switch (inst.kind()) {
  14. case SemIR::ImportRefUnused::Kind:
  15. // Resolve before merging.
  16. TryResolveImportRefUnused(context, inst_id);
  17. break;
  18. case SemIR::ImportRefUsed::Kind:
  19. // Already resolved.
  20. break;
  21. case SemIR::Namespace::Kind:
  22. // Return back the namespace directly.
  23. return inst;
  24. default:
  25. CARBON_FATAL() << "Unexpected inst kind passed to ResolveMergeableInst: "
  26. << inst;
  27. }
  28. auto const_id = context.constant_values().Get(inst_id);
  29. // TODO: Function and type declarations are constant, but `var` declarations
  30. // are non-constant and should still merge.
  31. if (!const_id.is_constant()) {
  32. return std::nullopt;
  33. }
  34. return context.insts().Get(const_id.inst_id());
  35. }
  36. auto MergeImportRef(Context& context, SemIR::InstId new_inst_id,
  37. SemIR::InstId prev_inst_id) -> void {
  38. auto new_inst = ResolveMergeableInst(context, new_inst_id);
  39. auto prev_inst = ResolveMergeableInst(context, prev_inst_id);
  40. if (!new_inst || !prev_inst) {
  41. // TODO: Once `var` declarations get an associated instruction for handling,
  42. // it might be more appropriate to return without diagnosing here, to handle
  43. // invalid declarations.
  44. context.DiagnoseDuplicateName(new_inst_id, prev_inst_id);
  45. return;
  46. }
  47. if (new_inst->kind() != prev_inst->kind()) {
  48. context.DiagnoseDuplicateName(new_inst_id, prev_inst_id);
  49. return;
  50. }
  51. switch (new_inst->kind()) {
  52. case SemIR::FunctionDecl::Kind: {
  53. auto new_fn = context.functions().Get(
  54. new_inst->As<SemIR::FunctionDecl>().function_id);
  55. auto prev_fn_id = prev_inst->As<SemIR::FunctionDecl>().function_id;
  56. // TODO: May need to "spoil" the new function to prevent it from being
  57. // emitted, since it will already be added.
  58. MergeFunctionRedecl(context, context.insts().GetLocId(new_inst_id),
  59. new_fn,
  60. /*new_is_definition=*/false, prev_fn_id,
  61. /*prev_is_imported=*/true);
  62. return;
  63. }
  64. default:
  65. context.TODO(new_inst_id, "Merging not yet supported.");
  66. return;
  67. }
  68. }
  69. } // namespace Carbon::Check