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

Code before:
      case clang::DiagnosticsEngine::Warning:
      case clang::DiagnosticsEngine::Error:
      case clang::DiagnosticsEngine::Fatal: {
        CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning, "C++:\n{0}",
                          std::string);
        CARBON_DIAGNOSTIC(CppInteropParseError, Error, "C++:\n{0}",
                          std::string);
        CARBON_DIAGNOSTIC(InCppImport, Note, "in `Cpp` import");

        // TODO: Use a more specific location.
        context_.emitter()
            .Build(SemIR::LocId::None,
                   diag_level == clang::DiagnosticsEngine::Warning
                       ? CppInteropParseWarning
                       : CppInteropParseError,
                   diagnostics_str)
            .Note(loc_, InCppImport)
            .Emit();
        return;
      }
    }
  }

 private:
  // The type-checking context in which we're running Clang.
  Context& context_;

  // The location that triggered calling Clang.
  SemIRLoc loc_;
};

}  // namespace

// Returns an AST for the C++ imports and a bool that represents whether
// compilation errors where encountered or the generated AST is null due to an
// error.
// TODO: Consider to always have a (non-null) AST.
static auto GenerateAst(Context& context, llvm::StringRef importing_file_path,
                        llvm::ArrayRef<Parse::Tree::PackagingNames> imports,
                        llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs)
    -> std::pair<std::unique_ptr<clang::ASTUnit>, bool> {
  // TODO: Use all import locations by referring each Clang diagnostic to the
  // relevant import.
  SemIRLoc loc = imports.back().node_id;

  std::string diagnostics_str;
  llvm::raw_string_ostream diagnostics_stream(diagnostics_str);

  CarbonClangDiagnosticConsumer diagnostics_consumer(context, loc);

  // TODO: Share compilation flags with ClangRunner.

Review comment (suggestion):
```suggestion
  Context* context_;
```

Style: "When storing an object's address as a non-owned member, prefer storing a pointer."

Code after:
      }
      case clang::DiagnosticsEngine::Warning:
      case clang::DiagnosticsEngine::Error:
      case clang::DiagnosticsEngine::Fatal: {
        // TODO: Adjust diagnostics to drop the Carbon file here, and then
        // remove the "C++:\n" prefix.
        CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning, "C++:\n{0}",
                          std::string);
        CARBON_DIAGNOSTIC(CppInteropParseError, Error, "C++:\n{0}",
                          std::string);
        // TODO: This should be part of the location, instead of added as a note
        // here.
        CARBON_DIAGNOSTIC(InCppImport, Note, "in `Cpp` import");

        // TODO: Use a more specific location.
        context_->emitter()
            .Build(SemIR::LocId::None,
                   diag_level == clang::DiagnosticsEngine::Warning
                       ? CppInteropParseWarning
                       : CppInteropParseError,
                   diagnostics_str)
            .Note(loc_, InCppImport)
            .Emit();
        return;
      }
    }
  }

 private:
  // The type-checking context in which we're running Clang.
  Context* context_;

  // The location that triggered calling Clang.
  SemIRLoc loc_;
};

}  // namespace

// Returns an AST for the C++ imports and a bool that represents whether
// compilation errors where encountered or the generated AST is null due to an
// error.
// TODO: Consider to always have a (non-null) AST.
static auto GenerateAst(Context& context, llvm::StringRef importing_file_path,
                        llvm::ArrayRef<Parse::Tree::PackagingNames> imports,
                        llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs)
    -> std::pair<std::unique_ptr<clang::ASTUnit>, bool> {
  // TODO: Use all import locations by referring each Clang diagnostic to the
  // relevant import.
  SemIRLoc loc = imports.back().node_id;

  std::string diagnostics_str;