Repository: carbon-language/carbon-lang
File: toolchain/driver/clang_runner.cpp (C++)

Code before:
          RunClangCC1(*installation_, fs_, cstr_args, enable_leaking);
      // TODO: Should this be forwarding the full exit code?
      return exit_code == 0;
    }

    // Other CC1-based invocations need to dispatch into the `clang_main`
    // routine to work correctly. This means they're not reliable in a library
    // context but currently there is too much logic to reasonably extract here.
    // This at least allows simple cases (often when directly used on the
    // command line) to work correctly.
    //
    // TODO: Factor the relevant code paths into a library API or move this into
    // the busybox dispatch logic.
    CARBON_VLOG("Calling clang_main for a cc1-based invocation...");
    // cstr_args[0] will be the `clang_path` so we don't need the prepend arg.
    llvm::ToolContext tool_context = {
        .Path = cstr_args[0], .PrependArg = "clang", .NeedsPrependArg = false};
    int exit_code = clang_main(
        cstr_args.size(), const_cast<char**>(cstr_args.data()), tool_context);
    // TODO: Should this be forwarding the full exit code?
    return exit_code == 0;
  }

  // Rebuild the args as C-string args.
  llvm::SmallVector<const char*, 64> cstr_args =
      BuildCStrArgs(clang_path, prefix_args, args, cstr_arg_storage);

  CARBON_VLOG("Running Clang driver with the following arguments:\n");
  for (const char* cstr_arg : llvm::ArrayRef(cstr_args)) {
    CARBON_VLOG("    '{0}'\n", cstr_arg);
  }

  // Create the diagnostic options and parse arguments controlling them out of
  // our arguments.
  std::unique_ptr<clang::DiagnosticOptions> diagnostic_options =
      clang::CreateAndPopulateDiagOpts(cstr_args);

  // TODO: We don't yet support serializing diagnostics the way the actual
  // `clang` command line does. Unclear if we need to or not, but it would need
  // a bit more logic here to set up chained consumers.
  clang::TextDiagnosticPrinter diagnostic_client(llvm::errs(),
                                                 *diagnostic_options);

  // Note that the `DiagnosticsEngine` takes ownership (via a ref count) of the
  // DiagnosticIDs, unlike the other parameters.
  clang::DiagnosticsEngine diagnostics(clang::DiagnosticIDs::create(),
                                       *diagnostic_options, &diagnostic_client,
                                       /*ShouldOwnClient=*/false);
  clang::ProcessWarningOptions(diagnostics, *diagnostic_options, *fs_);

  // Note that we configure the driver's *default* target here, not the expected

Review comment (suggestion):
I must be missing something obvious, but where's `prefix_args` coming from? I can't find any other code that mentions it, or even its declaration.

Code after:
      int exit_code =
          RunClangCC1(*installation_, fs_, cstr_args, enable_leaking);
      // TODO: Should this be forwarding the full exit code?
      return exit_code == 0;
    }

    // Other CC1-based invocations need to dispatch into the `clang_main`
    // routine to work correctly. This means they're not reliable in a library
    // context but currently there is too much logic to reasonably extract here.
    // This at least allows simple cases (often when directly used on the
    // command line) to work correctly.
    //
    // TODO: Factor the relevant code paths into a library API or move this into
    // the busybox dispatch logic.
    CARBON_VLOG("Calling clang_main for a cc1-based invocation...");
    // cstr_args[0] will be the `clang_path` so we don't need the prepend arg.
    llvm::ToolContext tool_context = {
        .Path = cstr_args[0], .PrependArg = "clang", .NeedsPrependArg = false};
    int exit_code = clang_main(
        cstr_args.size(), const_cast<char**>(cstr_args.data()), tool_context);
    // TODO: Should this be forwarding the full exit code?
    return exit_code == 0;
  }

  CARBON_VLOG("Running Clang driver with the following arguments:\n");
  for (const char* cstr_arg : llvm::ArrayRef(cstr_args)) {
    CARBON_VLOG("    '{0}'\n", cstr_arg);
  }

  // Create the diagnostic options and parse arguments controlling them out of
  // our arguments.
  std::unique_ptr<clang::DiagnosticOptions> diagnostic_options =
      clang::CreateAndPopulateDiagOpts(cstr_args);

  // TODO: We don't yet support serializing diagnostics the way the actual
  // `clang` command line does. Unclear if we need to or not, but it would need
  // a bit more logic here to set up chained consumers.
  clang::TextDiagnosticPrinter diagnostic_client(llvm::errs(),
                                                 *diagnostic_options);

  // Note that the `DiagnosticsEngine` takes ownership (via a ref count) of the
  // DiagnosticIDs, unlike the other parameters.
  clang::DiagnosticsEngine diagnostics(clang::DiagnosticIDs::create(),
                                       *diagnostic_options, &diagnostic_client,
                                       /*ShouldOwnClient=*/false);
  clang::ProcessWarningOptions(diagnostics, *diagnostic_options, *fs_);

  // Note that we configure the driver's *default* target here, not the expected
  // target as that will be parsed out of the command line below.
  clang::driver::Driver driver(clang_path, llvm::sys::getDefaultTargetTriple(),
                               diagnostics, "clang LLVM compiler", fs_);