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());
  }
}
Example #2
0
    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);
    }