function.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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 check_syntax)
  13. -> bool {
  14. if (!CheckRedeclParamsMatch(context, DeclParams(new_function),
  15. DeclParams(prev_function), substitutions,
  16. check_syntax)) {
  17. return false;
  18. }
  19. // TODO: Pass a specific ID for `prev_function` instead of substitutions and
  20. // use it here.
  21. auto new_return_type_id =
  22. new_function.GetDeclaredReturnType(context.sem_ir());
  23. auto prev_return_type_id = prev_function.GetDeclaredReturnType(
  24. context.sem_ir(), SemIR::SpecificId::Invalid);
  25. if (new_return_type_id == SemIR::TypeId::Error ||
  26. prev_return_type_id == SemIR::TypeId::Error) {
  27. return false;
  28. }
  29. if (prev_return_type_id.is_valid()) {
  30. prev_return_type_id =
  31. SubstType(context, prev_return_type_id, substitutions);
  32. }
  33. if (!context.types().AreEqualAcrossDeclarations(new_return_type_id,
  34. prev_return_type_id)) {
  35. CARBON_DIAGNOSTIC(
  36. FunctionRedeclReturnTypeDiffers, Error,
  37. "Function redeclaration differs because return type is `{0}`.",
  38. SemIR::TypeId);
  39. CARBON_DIAGNOSTIC(
  40. FunctionRedeclReturnTypeDiffersNoReturn, Error,
  41. "Function redeclaration differs because no return type is provided.");
  42. auto diag =
  43. new_return_type_id.is_valid()
  44. ? context.emitter().Build(new_function.decl_id,
  45. FunctionRedeclReturnTypeDiffers,
  46. new_return_type_id)
  47. : context.emitter().Build(new_function.decl_id,
  48. FunctionRedeclReturnTypeDiffersNoReturn);
  49. if (prev_return_type_id.is_valid()) {
  50. CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePrevious, Note,
  51. "Previously declared with return type `{0}`.",
  52. SemIR::TypeId);
  53. diag.Note(prev_function.decl_id, FunctionRedeclReturnTypePrevious,
  54. prev_return_type_id);
  55. } else {
  56. CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePreviousNoReturn, Note,
  57. "Previously declared with no return type.");
  58. diag.Note(prev_function.decl_id,
  59. FunctionRedeclReturnTypePreviousNoReturn);
  60. }
  61. diag.Emit();
  62. return false;
  63. }
  64. return true;
  65. }
  66. auto CheckFunctionReturnType(Context& context, SemIRLoc loc,
  67. SemIR::Function& function,
  68. SemIR::SpecificId specific_id)
  69. -> SemIR::ReturnTypeInfo {
  70. auto return_info = SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(),
  71. function, specific_id);
  72. // If we couldn't determine the return information due to the return type
  73. // being incomplete, try to complete it now.
  74. if (return_info.init_repr.kind == SemIR::InitRepr::Incomplete) {
  75. auto diagnose_incomplete_return_type = [&] {
  76. CARBON_DIAGNOSTIC(IncompleteTypeInFunctionReturnType, Error,
  77. "Function returns incomplete type `{0}`.",
  78. SemIR::TypeId);
  79. return context.emitter().Build(loc, IncompleteTypeInFunctionReturnType,
  80. return_info.type_id);
  81. };
  82. // TODO: Consider suppressing the diagnostic if we've already diagnosed a
  83. // definition or call to this function.
  84. if (context.TryToCompleteType(return_info.type_id,
  85. diagnose_incomplete_return_type)) {
  86. return_info = SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(),
  87. function, specific_id);
  88. }
  89. }
  90. return return_info;
  91. }
  92. } // namespace Carbon::Check