Repository: carbon-language/carbon-lang
File: toolchain/lex/string_literal.cpp (C++)

Code before:
  if (hash_level_ != 0) {
    CARBON_DIAGNOSTIC(CharLiteralRaw, Error,
                      "unexpected `#` before character literal");
    emitter.Emit(text_.begin(), CharLiteralRaw);
  }

  // Allocate a buffer sized to the content. Note it's possible this could be
  // more efficient/faster with a `ExpandEscapeSequencesAndRemoveIndent`
  // implementation aware of the buffer size, but this is trying to share logic
  // with string expansion.
  llvm::SmallVector<char, 0> buffer;
  buffer.resize_for_overwrite(content_.size());

  auto result = ExpandEscapeSequencesAndRemoveIndent(
      emitter, content_, 0, /*indent=*/llvm::StringRef(), buffer.data());
  CARBON_CHECK(result.size() <= content_.size(),
               "Content grew from {0} to {1}: `{2}`", content_.size(),
               result.size(), content_);

  llvm::UTF32 target[1];
  const auto* source_cursor =
      reinterpret_cast<const llvm::UTF8*>(result.begin());
  llvm::UTF32* target_cursor = target;
  llvm::ConversionResult conv_result = llvm::ConvertUTF8toUTF32(
      &source_cursor, reinterpret_cast<const llvm::UTF8*>(result.end()),
      &target_cursor, &target[1], llvm::strictConversion);

  switch (conv_result) {
    case llvm::conversionOK: {
      if (target_cursor == target) {
        CARBON_DIAGNOSTIC(CharLiteralEmpty, Error, "empty character literal");
        emitter.Emit(text_.begin(), CharLiteralEmpty);
        return std::nullopt;
      }
      return CharLiteralValue{.value = static_cast<int32_t>(target[0])};
    }
    case llvm::sourceExhausted: {
      CARBON_DIAGNOSTIC(CharLiteralUnderflow, Error, "incomplete UTF-8");
      emitter.Emit(text_.begin(), CharLiteralUnderflow);
      return std::nullopt;
    }
    case llvm::targetExhausted: {
      CARBON_DIAGNOSTIC(CharLiteralOverflow, Error, "too many characters");
      emitter.Emit(text_.begin(), CharLiteralOverflow);
      return std::nullopt;
    }
    case llvm::sourceIllegal: {
      CARBON_DIAGNOSTIC(CharLiteralInvalidUTF8, Error,
                        "invalid UTF-8 character");
      emitter.Emit(text_.begin(), CharLiteralInvalidUTF8);
      return std::nullopt;

Review comment (suggestion):
```suggestion
      &target_cursor, std::end(target), llvm::strictConversion);
```

Code after:
  if (hash_level_ != 0) {
    CARBON_DIAGNOSTIC(CharLiteralRaw, Error,
                      "unexpected `#` before character literal");
    emitter.Emit(text_.begin(), CharLiteralRaw);
  }

  // Allocate a buffer sized to the content. Note it's possible this could be
  // more efficient/faster with a `ExpandEscapeSequencesAndRemoveIndent`
  // implementation aware of the buffer size, but this is trying to share logic
  // with string expansion.
  llvm::SmallVector<char> buffer;
  buffer.resize_for_overwrite(content_.size());

  auto result = ExpandEscapeSequencesAndRemoveIndent(
      emitter, content_, 0, /*indent=*/llvm::StringRef(), buffer.data());
  CARBON_CHECK(result.size() <= content_.size(),
               "Content grew from {0} to {1}: `{2}`", content_.size(),
               result.size(), content_);

  llvm::UTF32 target[1];
  const auto* source_cursor =
      reinterpret_cast<const llvm::UTF8*>(result.begin());
  llvm::UTF32* target_cursor = target;
  llvm::ConversionResult conv_result = llvm::ConvertUTF8toUTF32(
      &source_cursor, reinterpret_cast<const llvm::UTF8*>(result.end()),
      &target_cursor, std::end(target), llvm::strictConversion);

  switch (conv_result) {
    case llvm::conversionOK: {
      if (target_cursor == target) {
        CARBON_DIAGNOSTIC(CharLiteralEmpty, Error, "empty character literal");
        emitter.Emit(text_.begin(), CharLiteralEmpty);
        return std::nullopt;
      }
      return CharLiteralValue{.value = static_cast<int32_t>(target[0])};
    }
    case llvm::sourceExhausted: {
      CARBON_DIAGNOSTIC(CharLiteralUnderflow, Error, "incomplete UTF-8");
      emitter.Emit(text_.begin(), CharLiteralUnderflow);
      return std::nullopt;
    }
    case llvm::targetExhausted: {
      CARBON_DIAGNOSTIC(CharLiteralOverflow, Error, "too many characters");
      emitter.Emit(text_.begin(), CharLiteralOverflow);
      return std::nullopt;
    }
    case llvm::sourceIllegal: {
      CARBON_DIAGNOSTIC(CharLiteralInvalidUTF8, Error,
                        "invalid UTF-8 character");
      emitter.Emit(text_.begin(), CharLiteralInvalidUTF8);
      return std::nullopt;