semantics_handle_index.cpp 4.0 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 "llvm/ADT/APSInt.h"
  5. #include "toolchain/semantics/semantics_context.h"
  6. #include "toolchain/semantics/semantics_node.h"
  7. #include "toolchain/semantics/semantics_node_kind.h"
  8. namespace Carbon {
  9. auto SemanticsHandleIndexExpressionStart(SemanticsContext& /*context*/,
  10. ParseTree::Node /*parse_node*/)
  11. -> bool {
  12. // Leave the expression on the stack for IndexExpression.
  13. return true;
  14. }
  15. auto SemanticsHandleIndexExpression(SemanticsContext& context,
  16. ParseTree::Node parse_node) -> bool {
  17. CARBON_DIAGNOSTIC(OutOfBoundsAccess, Error,
  18. "Index `{0}` is past the end of `{1}`.", llvm::APSInt,
  19. std::string);
  20. auto index_node_id = context.node_stack().PopExpression();
  21. auto index_node = context.semantics_ir().GetNode(index_node_id);
  22. auto name_node_id = context.node_stack().PopExpression();
  23. auto name_node = context.semantics_ir().GetNode(name_node_id);
  24. auto name_type_id =
  25. context.semantics_ir().GetTypeAllowBuiltinTypes(name_node.type_id());
  26. auto name_type_node = context.semantics_ir().GetNode(name_type_id);
  27. if (name_type_node.kind() == SemanticsNodeKind::ArrayType) {
  28. auto [bound_id, type_id] = name_type_node.GetAsArrayType();
  29. if (index_node.kind() == SemanticsNodeKind::IntegerLiteral) {
  30. const auto& index_val = context.semantics_ir().GetIntegerLiteral(
  31. index_node.GetAsIntegerLiteral());
  32. if (index_val.uge(context.semantics_ir().GetArrayBoundValue(bound_id))) {
  33. context.emitter().Emit(
  34. parse_node, OutOfBoundsAccess,
  35. llvm::APSInt(index_val, /*isUnsigned=*/true),
  36. context.semantics_ir().StringifyType(name_node.type_id()));
  37. } else {
  38. context.AddNodeAndPush(
  39. parse_node, SemanticsNode::ArrayIndex::Make(
  40. parse_node, type_id, name_node_id, index_node_id));
  41. return true;
  42. }
  43. } else if (context.ImplicitAsRequired(
  44. index_node.parse_node(), index_node_id,
  45. context.CanonicalizeType(
  46. SemanticsNodeId::BuiltinIntegerType)) !=
  47. SemanticsNodeId::BuiltinError) {
  48. context.AddNodeAndPush(
  49. parse_node, SemanticsNode::ArrayIndex::Make(
  50. parse_node, type_id, name_node_id, index_node_id));
  51. return true;
  52. }
  53. } else if (name_type_node.kind() == SemanticsNodeKind::TupleType) {
  54. if (index_node.kind() == SemanticsNodeKind::IntegerLiteral) {
  55. const auto& index_val = context.semantics_ir().GetIntegerLiteral(
  56. index_node.GetAsIntegerLiteral());
  57. auto type_block =
  58. context.semantics_ir().GetTypeBlock(name_type_node.GetAsTupleType());
  59. if (index_val.uge(static_cast<uint64_t>(type_block.size()))) {
  60. context.emitter().Emit(
  61. parse_node, OutOfBoundsAccess,
  62. llvm::APSInt(index_val, /*isUnsigned=*/true),
  63. context.semantics_ir().StringifyType(name_node.type_id()));
  64. } else {
  65. context.AddNodeAndPush(
  66. parse_node, SemanticsNode::TupleIndex::Make(
  67. parse_node, type_block[index_val.getZExtValue()],
  68. name_node_id, index_node_id));
  69. return true;
  70. }
  71. } else {
  72. CARBON_DIAGNOSTIC(NondeterministicType, Error,
  73. "Type cannot be determined at compile time.");
  74. context.emitter().Emit(parse_node, NondeterministicType);
  75. }
  76. } else if (name_type_id != SemanticsNodeId::BuiltinError) {
  77. CARBON_DIAGNOSTIC(InvalidIndexExpression, Error,
  78. "Invalid index expression.");
  79. context.emitter().Emit(parse_node, InvalidIndexExpression);
  80. }
  81. context.node_stack().Push(parse_node, SemanticsNodeId::BuiltinError);
  82. return true;
  83. }
  84. } // namespace Carbon