handle_statement.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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/context.h"
  5. #include "toolchain/check/convert.h"
  6. #include "toolchain/sem_ir/node.h"
  7. namespace Carbon::Check {
  8. // TODO: Find a better home for this. We'll likely need it for more than just
  9. // expression statements.
  10. static auto HandleDiscardedExpression(Context& context, SemIR::NodeId expr_id)
  11. -> void {
  12. // If we discard an initializing expression, convert it to a value or
  13. // reference so that it has something to initialize.
  14. auto expr = context.semantics_ir().GetNode(expr_id);
  15. Convert(context, expr.parse_node(), expr_id,
  16. {.kind = ConversionTarget::Discarded, .type_id = expr.type_id()});
  17. // TODO: This will eventually need to do some "do not discard" analysis.
  18. }
  19. auto HandleExpressionStatement(Context& context, Parse::Node /*parse_node*/)
  20. -> bool {
  21. HandleDiscardedExpression(context, context.node_stack().PopExpression());
  22. return true;
  23. }
  24. auto HandleReturnStatement(Context& context, Parse::Node parse_node) -> bool {
  25. CARBON_CHECK(!context.return_scope_stack().empty());
  26. auto fn_node = context.semantics_ir().GetNodeAs<SemIR::FunctionDeclaration>(
  27. context.return_scope_stack().back());
  28. const auto& callable =
  29. context.semantics_ir().GetFunction(fn_node.function_id);
  30. if (context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
  31. Parse::NodeKind::ReturnStatementStart) {
  32. context.node_stack()
  33. .PopAndDiscardSoloParseNode<Parse::NodeKind::ReturnStatementStart>();
  34. if (callable.return_type_id.is_valid()) {
  35. // TODO: Add a note pointing at the return type's parse node.
  36. CARBON_DIAGNOSTIC(ReturnStatementMissingExpression, Error,
  37. "Must return a {0}.", std::string);
  38. context.emitter()
  39. .Build(parse_node, ReturnStatementMissingExpression,
  40. context.semantics_ir().StringifyType(callable.return_type_id))
  41. .Emit();
  42. }
  43. context.AddNode(SemIR::Return(parse_node));
  44. } else {
  45. auto arg = context.node_stack().PopExpression();
  46. context.node_stack()
  47. .PopAndDiscardSoloParseNode<Parse::NodeKind::ReturnStatementStart>();
  48. if (!callable.return_type_id.is_valid()) {
  49. CARBON_DIAGNOSTIC(
  50. ReturnStatementDisallowExpression, Error,
  51. "No return expression should be provided in this context.");
  52. CARBON_DIAGNOSTIC(ReturnStatementImplicitNote, Note,
  53. "There was no return type provided.");
  54. context.emitter()
  55. .Build(parse_node, ReturnStatementDisallowExpression)
  56. .Note(fn_node.parse_node, ReturnStatementImplicitNote)
  57. .Emit();
  58. } else if (callable.return_slot_id.is_valid()) {
  59. arg = Initialize(context, parse_node, callable.return_slot_id, arg);
  60. } else {
  61. arg = ConvertToValueOfType(context, parse_node, arg,
  62. callable.return_type_id);
  63. }
  64. context.AddNode(SemIR::ReturnExpression(parse_node, arg));
  65. }
  66. // Switch to a new, unreachable, empty node block. This typically won't
  67. // contain any semantics IR, but it can do if there are statements following
  68. // the `return` statement.
  69. context.node_block_stack().Pop();
  70. context.node_block_stack().PushUnreachable();
  71. return true;
  72. }
  73. auto HandleReturnStatementStart(Context& context, Parse::Node parse_node)
  74. -> bool {
  75. // No action, just a bracketing node.
  76. context.node_stack().Push(parse_node);
  77. return true;
  78. }
  79. } // namespace Carbon::Check