function.cpp 4.1 KB

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