diff --git a/clang/lib/Frontend/PlistDiagnostics.cpp b/clang/lib/Frontend/PlistDiagnostics.cpp index 80ee2c2e8eba..92cafe6d1cbe 100644 --- a/clang/lib/Frontend/PlistDiagnostics.cpp +++ b/clang/lib/Frontend/PlistDiagnostics.cpp @@ -29,6 +29,40 @@ namespace clang { class Preprocessor; } +namespace { +struct CompareDiagnostics { + // Compare if 'X' is "<" than 'Y'. + bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const { + // First compare by location + const FullSourceLoc &XLoc = X->getLocation().asLocation(); + const FullSourceLoc &YLoc = Y->getLocation().asLocation(); + if (XLoc < YLoc) + return true; + if (XLoc != YLoc) + return false; + + // Next, compare by bug type. + llvm::StringRef XBugType = X->getBugType(); + llvm::StringRef YBugType = Y->getBugType(); + if (XBugType < YBugType) + return true; + if (XBugType != YBugType) + return false; + + // Next, compare by bug description. + llvm::StringRef XDesc = X->getDescription(); + llvm::StringRef YDesc = Y->getDescription(); + if (XDesc < YDesc) + return true; + if (XDesc != YDesc) + return false; + + // FIXME: Further refine by comparing PathDiagnosticPieces? + return false; + } +}; +} + namespace { class PlistDiagnostics : public PathDiagnosticClient { std::vector BatchedDiags; @@ -314,6 +348,11 @@ void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl return; flushed = true; + + // Sort the diagnostics so that they are always emitted in a deterministic + // order. + if (!BatchedDiags.empty()) + std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics()); // Build up a set of FIDs that we use by scanning the locations and // ranges of the diagnostics.