semantics_handle_statement.cpp 3.0 KB

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