function.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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/function.h"
  5. #include "toolchain/check/merge.h"
  6. #include "toolchain/check/subst.h"
  7. #include "toolchain/sem_ir/ids.h"
  8. namespace Carbon::Check {
  9. auto CheckFunctionTypeMatches(Context& context,
  10. const SemIR::Function& new_function,
  11. const SemIR::Function& prev_function,
  12. Substitutions substitutions) -> bool {
  13. if (!CheckRedeclParamsMatch(context, DeclParams(new_function),
  14. DeclParams(prev_function), substitutions)) {
  15. return false;
  16. }
  17. auto new_return_type_id = new_function.declared_return_type(context.sem_ir());
  18. auto prev_return_type_id =
  19. prev_function.declared_return_type(context.sem_ir());
  20. if (new_return_type_id == SemIR::TypeId::Error ||
  21. prev_return_type_id == SemIR::TypeId::Error) {
  22. return false;
  23. }
  24. if (prev_return_type_id.is_valid()) {
  25. prev_return_type_id =
  26. SubstType(context, prev_return_type_id, substitutions);
  27. }
  28. if (new_return_type_id != prev_return_type_id) {
  29. CARBON_DIAGNOSTIC(
  30. FunctionRedeclReturnTypeDiffers, Error,
  31. "Function redeclaration differs because return type is `{0}`.",
  32. SemIR::TypeId);
  33. CARBON_DIAGNOSTIC(
  34. FunctionRedeclReturnTypeDiffersNoReturn, Error,
  35. "Function redeclaration differs because no return type is provided.");
  36. auto diag =
  37. new_return_type_id.is_valid()
  38. ? context.emitter().Build(new_function.decl_id,
  39. FunctionRedeclReturnTypeDiffers,
  40. new_return_type_id)
  41. : context.emitter().Build(new_function.decl_id,
  42. FunctionRedeclReturnTypeDiffersNoReturn);
  43. if (prev_return_type_id.is_valid()) {
  44. CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePrevious, Note,
  45. "Previously declared with return type `{0}`.",
  46. SemIR::TypeId);
  47. diag.Note(prev_function.decl_id, FunctionRedeclReturnTypePrevious,
  48. prev_return_type_id);
  49. } else {
  50. CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePreviousNoReturn, Note,
  51. "Previously declared with no return type.");
  52. diag.Note(prev_function.decl_id,
  53. FunctionRedeclReturnTypePreviousNoReturn);
  54. }
  55. diag.Emit();
  56. return false;
  57. }
  58. return true;
  59. }
  60. auto CheckFunctionReturnType(Context& context, SemIRLoc loc,
  61. SemIR::Function& function) -> void {
  62. // If we have already checked the return type, we have nothing to do.
  63. if (function.return_slot != SemIR::Function::ReturnSlot::NotComputed) {
  64. return;
  65. }
  66. if (!function.return_storage_id.is_valid()) {
  67. // Implicit `-> ()` has no return slot.
  68. function.return_slot = SemIR::Function::ReturnSlot::Absent;
  69. return;
  70. }
  71. auto return_type_id = function.declared_return_type(context.sem_ir());
  72. CARBON_CHECK(return_type_id.is_valid())
  73. << "Have return storage but no return type.";
  74. // Check the return type is complete. Only diagnose incompleteness if we've
  75. // not already done so.
  76. auto diagnose_incomplete_return_type = [&] {
  77. CARBON_DIAGNOSTIC(IncompleteTypeInFunctionReturnType, Error,
  78. "Function returns incomplete type `{0}`.", SemIR::TypeId);
  79. return context.emitter().Build(loc, IncompleteTypeInFunctionReturnType,
  80. return_type_id);
  81. };
  82. if (!context.TryToCompleteType(
  83. return_type_id,
  84. function.return_slot == SemIR::Function::ReturnSlot::Error
  85. ? std::nullopt
  86. : std::optional(diagnose_incomplete_return_type))) {
  87. function.return_slot = SemIR::Function::ReturnSlot::Error;
  88. } else if (SemIR::GetInitRepr(context.sem_ir(), return_type_id)
  89. .has_return_slot()) {
  90. function.return_slot = SemIR::Function::ReturnSlot::Present;
  91. } else {
  92. function.return_slot = SemIR::Function::ReturnSlot::Absent;
  93. }
  94. }
  95. } // namespace Carbon::Check