Repository: carbon-language/carbon-lang
File: toolchain/check/cpp/generate_ast.cpp (C++)

Code before:
  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(
      clang::CompilerInstance::createDiagnostics(
          *fs, invocation->getDiagnosticOpts(),
          new CarbonClangDiagnosticConsumer(context, invocation),
          /*ShouldOwnClient=*/true));

  // Extract the input from the frontend invocation and make sure it makes
  // sense.
  const auto& inputs = invocation->getFrontendOpts().Inputs;
  CARBON_CHECK(inputs.size() == 1 &&
               inputs[0].getKind().getLanguage() == clang::Language::CXX &&
               inputs[0].getKind().getFormat() == clang::InputKind::Source);
  llvm::StringRef file_name = inputs[0].getFile();

  // Remap the imports file name to the corresponding `#include`s.
  // TODO: Modify the frontend options to specify this memory buffer as input
  // instead of remapping the file.
  std::string includes = GenerateCppIncludesHeaderCode(context, imports);
  auto includes_buffer =
      llvm::MemoryBuffer::getMemBufferCopy(includes, file_name);
  invocation->getPreprocessorOpts().addRemappedFile(file_name,
                                                    includes_buffer.release());

  clang::DiagnosticErrorTrap trap(*diags);

  auto clang = std::make_unique<clang::CompilerInstance>(invocation);
  auto& clang_ref = *clang.get();
  context.sem_ir().set_cpp_file(
      std::make_unique<SemIR::CppFile>(std::move(clang)));

  clang_ref.setDiagnostics(diags);
  clang_ref.setVirtualFileSystem(fs);
  clang_ref.createFileManager();
  clang_ref.createSourceManager();
  if (!clang_ref.createTarget()) {
    return false;
  }

  context.set_cpp_context(std::make_unique<CppContext>(
      std::make_unique<GenerateASTAction>(context)));

  if (!context.cpp_context()->action().BeginSourceFile(clang_ref, inputs[0])) {
    return false;
  }

  if (llvm::Error error = context.cpp_context()->action().Execute()) {
    // `Execute` currently never fails, but its contract allows it to.
    context.TODO(SemIR::LocId::None, "failed to execute clang action: " +
                                         llvm::toString(std::move(error)));
    return false;
  }

Review comment (suggestion):
I personally always get confused by "compiler instance" versus "compiler invocation" (classic human reading optimization - they're similar lengths, both start with "in", etc) - so, sort of related, I worry calling this thing "clang" would confuse me even more (compared to calling it "compiler_instance" here and elsewhere)... but not an especially firm suggestion/critique

Code after:
  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(
      clang::CompilerInstance::createDiagnostics(
          *fs, invocation->getDiagnosticOpts(),
          new CarbonClangDiagnosticConsumer(context, invocation),
          /*ShouldOwnClient=*/true));

  // Extract the input from the frontend invocation and make sure it makes
  // sense.
  const auto& inputs = invocation->getFrontendOpts().Inputs;
  CARBON_CHECK(inputs.size() == 1 &&
               inputs[0].getKind().getLanguage() == clang::Language::CXX &&
               inputs[0].getKind().getFormat() == clang::InputKind::Source);
  llvm::StringRef file_name = inputs[0].getFile();

  // Remap the imports file name to the corresponding `#include`s.
  // TODO: Modify the frontend options to specify this memory buffer as input
  // instead of remapping the file.
  std::string includes = GenerateCppIncludesHeaderCode(context, imports);
  auto includes_buffer =
      llvm::MemoryBuffer::getMemBufferCopy(includes, file_name);
  invocation->getPreprocessorOpts().addRemappedFile(file_name,
                                                    includes_buffer.release());

  clang::DiagnosticErrorTrap trap(*diags);

  auto clang_instance_ptr =
      std::make_unique<clang::CompilerInstance>(invocation);
  auto& clang_instance = *clang_instance_ptr;
  context.sem_ir().set_cpp_file(
      std::make_unique<SemIR::CppFile>(std::move(clang_instance_ptr)));

  clang_instance.setDiagnostics(diags);
  clang_instance.setVirtualFileSystem(fs);
  clang_instance.createFileManager();
  clang_instance.createSourceManager();
  if (!clang_instance.createTarget()) {
    return false;
  }

  context.set_cpp_context(std::make_unique<CppContext>(
      std::make_unique<GenerateASTAction>(context)));

  if (!context.cpp_context()->action().BeginSourceFile(clang_instance,
                                                       inputs[0])) {
    return false;
  }

  if (llvm::Error error = context.cpp_context()->action().Execute()) {
    // `Execute` currently never fails, but its contract allows it to.
    context.TODO(SemIR::LocId::None, "failed to execute clang action: " +
                                         llvm::toString(std::move(error)));