semantics_handle_statement.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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/semantics/semantics_context.h"
  5. #include "toolchain/semantics/semantics_node.h"
  6. namespace Carbon::Check {
  7. auto HandleExpressionStatement(Context& context, ParseTree::Node /*parse_node*/)
  8. -> bool {
  9. context.HandleDiscardedExpression(context.node_stack().PopExpression());
  10. return true;
  11. }
  12. auto HandleReturnStatement(Context& context, ParseTree::Node parse_node)
  13. -> bool {
  14. CARBON_CHECK(!context.return_scope_stack().empty());
  15. const auto& fn_node =
  16. context.semantics_ir().GetNode(context.return_scope_stack().back());
  17. const auto& callable =
  18. context.semantics_ir().GetFunction(fn_node.GetAsFunctionDeclaration());
  19. if (context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
  20. ParseNodeKind::ReturnStatementStart) {
  21. context.node_stack()
  22. .PopAndDiscardSoloParseNode<ParseNodeKind::ReturnStatementStart>();
  23. if (callable.return_type_id.is_valid()) {
  24. // TODO: Add a note pointing at the return type's parse node.
  25. CARBON_DIAGNOSTIC(ReturnStatementMissingExpression, Error,
  26. "Must return a {0}.", std::string);
  27. context.emitter()
  28. .Build(parse_node, ReturnStatementMissingExpression,
  29. context.semantics_ir().StringifyType(callable.return_type_id))
  30. .Emit();
  31. }
  32. context.AddNode(SemIR::Node::Return::Make(parse_node));
  33. } else {
  34. auto arg = context.node_stack().PopExpression();
  35. context.node_stack()
  36. .PopAndDiscardSoloParseNode<ParseNodeKind::ReturnStatementStart>();
  37. if (!callable.return_type_id.is_valid()) {
  38. CARBON_DIAGNOSTIC(
  39. ReturnStatementDisallowExpression, Error,
  40. "No return expression should be provided in this context.");
  41. CARBON_DIAGNOSTIC(ReturnStatementImplicitNote, Note,
  42. "There was no return type provided.");
  43. context.emitter()
  44. .Build(parse_node, ReturnStatementDisallowExpression)
  45. .Note(fn_node.parse_node(), ReturnStatementImplicitNote)
  46. .Emit();
  47. context.AddNode(SemIR::Node::ReturnExpression::Make(parse_node, arg));
  48. } else if (callable.return_slot_id.is_valid()) {
  49. context.Initialize(parse_node, callable.return_slot_id, arg);
  50. context.AddNode(SemIR::Node::Return::Make(parse_node));
  51. } else {
  52. arg = context.ConvertToValueOfType(parse_node, arg,
  53. callable.return_type_id);
  54. if (SemIR::GetInitializingRepresentation(context.semantics_ir(),
  55. callable.return_type_id)
  56. .kind == SemIR::InitializingRepresentation::None) {
  57. context.AddNode(SemIR::Node::Return::Make(parse_node));
  58. } else {
  59. context.AddNode(SemIR::Node::ReturnExpression::Make(parse_node, arg));
  60. }
  61. }
  62. }
  63. // Switch to a new, unreachable, empty node block. This typically won't
  64. // contain any semantics IR, but it can do if there are statements following
  65. // the `return` statement.
  66. context.node_block_stack().Pop();
  67. context.node_block_stack().PushUnreachable();
  68. return true;
  69. }
  70. auto HandleReturnStatementStart(Context& context, ParseTree::Node parse_node)
  71. -> bool {
  72. // No action, just a bracketing node.
  73. context.node_stack().Push(parse_node);
  74. return true;
  75. }
  76. } // namespace Carbon::Check