void ClangDiagnosticConsumer::HandleDiagnostic( clang::DiagnosticsEngine::Level clangDiagLevel, const clang::Diagnostic &clangDiag) { // Handle the module-not-found diagnostic specially if it's a top-level module // we're looking for. if (clangDiag.getID() == clang::diag::err_module_not_found && CurrentImport && clangDiag.getArgStdStr(0) == CurrentImport->getName()) { return; } const ASTContext &ctx = ImporterImpl.SwiftContext; if (clangDiag.getID() == clang::diag::err_module_not_built && CurrentImport && clangDiag.getArgStdStr(0) == CurrentImport->getName()) { SourceLoc loc = DiagLoc; if (clangDiag.getLocation().isValid()) loc = resolveSourceLocation(clangDiag.getSourceManager(), clangDiag.getLocation()); ctx.Diags.diagnose(loc, diag::clang_cannot_build_module, CurrentImport->getName()); return; } // Satisfy the default implementation (bookkeeping). if (DumpToStderr) TextDiagnosticPrinter::HandleDiagnostic(clangDiagLevel, clangDiag); else DiagnosticConsumer::HandleDiagnostic(clangDiagLevel, clangDiag); // FIXME: Map over source ranges in the diagnostic. auto emitDiag = [&ctx, this](clang::FullSourceLoc clangNoteLoc, clang::DiagnosticsEngine::Level clangDiagLevel, StringRef message) { decltype(diag::error_from_clang) diagKind; switch (clangDiagLevel) { case clang::DiagnosticsEngine::Ignored: return; case clang::DiagnosticsEngine::Note: diagKind = diag::note_from_clang; break; case clang::DiagnosticsEngine::Remark: // FIXME: We don't handle remarks yet. return; case clang::DiagnosticsEngine::Warning: diagKind = diag::warning_from_clang; break; case clang::DiagnosticsEngine::Error: case clang::DiagnosticsEngine::Fatal: // FIXME: What happens after a fatal error in the importer? diagKind = diag::error_from_clang; break; } SourceLoc noteLoc; if (clangNoteLoc.isValid()) noteLoc = resolveSourceLocation(clangNoteLoc.getManager(), clangNoteLoc); ctx.Diags.diagnose(noteLoc, diagKind, message); }; llvm::SmallString<128> message; clangDiag.FormatDiagnostic(message); if (clangDiag.getLocation().isInvalid()) { // Diagnostic about the compiler arguments. emitDiag(clang::FullSourceLoc(), clangDiagLevel, message); } else { assert(clangDiag.hasSourceManager()); ClangDiagRenderer renderer(ImporterImpl.getClangASTContext(), emitDiag); renderer.emitDiagnostic(clangDiag.getLocation(), clangDiagLevel, message, clangDiag.getRanges(), clangDiag.getFixItHints(), &clangDiag.getSourceManager()); } }
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) { if (m_manager) { llvm::SmallVector<char, 32> diag_str; Info.FormatDiagnostic(diag_str); diag_str.push_back('\0'); const char *data = diag_str.data(); lldb_private::DiagnosticSeverity severity; bool make_new_diagnostic = true; switch (DiagLevel) { case DiagnosticsEngine::Level::Fatal: case DiagnosticsEngine::Level::Error: severity = eDiagnosticSeverityError; break; case DiagnosticsEngine::Level::Warning: severity = eDiagnosticSeverityWarning; break; case DiagnosticsEngine::Level::Remark: case DiagnosticsEngine::Level::Ignored: severity = eDiagnosticSeverityRemark; break; case DiagnosticsEngine::Level::Note: m_manager->AppendMessageToDiagnostic(data); make_new_diagnostic = false; } if (make_new_diagnostic) { ClangDiagnostic *new_diagnostic = new ClangDiagnostic(data, severity, Info.getID()); m_manager->AddDiagnostic(new_diagnostic); // Don't store away warning fixits, since the compiler doesn't have enough // context in an expression for the warning to be useful. // FIXME: Should we try to filter out FixIts that apply to our generated // code, and not the user's expression? if (severity == eDiagnosticSeverityError) { size_t num_fixit_hints = Info.getNumFixItHints(); for (size_t i = 0; i < num_fixit_hints; i++) { const clang::FixItHint &fixit = Info.getFixItHint(i); if (!fixit.isNull()) new_diagnostic->AddFixitHint(fixit); } } } } m_passthrough->HandleDiagnostic(DiagLevel, Info); }