12815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//===-- CXLoadedDiagnostic.cpp - Handling of persisent diags ----*- C++ -*-===//
22815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//
32815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//                     The LLVM Compiler Infrastructure
42815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//
52815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// This file is distributed under the University of Illinois Open Source
62815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// License. See LICENSE.TXT for details.
72815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//
82815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//===----------------------------------------------------------------------===//
92815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//
102815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// Implements handling of persisent diagnostics.
112815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//
122815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//===----------------------------------------------------------------------===//
13153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
14153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "CXLoadedDiagnostic.h"
15153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "CXString.h"
16153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Basic/Diagnostic.h"
17153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Basic/FileManager.h"
18651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Basic/LLVM.h"
19176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Frontend/SerializedDiagnosticReader.h"
200e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/Frontend/SerializedDiagnostics.h"
21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/Optional.h"
223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h"
23153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/StringRef.h"
24153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/Twine.h"
25153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Bitcode/BitstreamReader.h"
26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/ErrorHandling.h"
27153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Support/MemoryBuffer.h"
28153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekusing namespace clang;
29153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
30153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
31153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
32153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
33153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
349ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenkotypedef llvm::DenseMap<unsigned, const char *> Strings;
35153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
36153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace {
37153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekclass CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
38153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekpublic:
39153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
4033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ~CXLoadedDiagnosticSetImpl() override {}
41153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
42153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BumpPtrAllocator Alloc;
43153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings Categories;
44153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings WarningFlags;
45153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings FileNames;
46153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
47153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileSystemOptions FO;
48153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileManager FakeFiles;
49153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::DenseMap<unsigned, const FileEntry *> Files;
509ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko
519ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  /// \brief Copy the string into our own allocator.
529ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  const char *copyString(StringRef Blob) {
53b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    char *mem = Alloc.Allocate<char>(Blob.size() + 1);
54b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    memcpy(mem, Blob.data(), Blob.size());
55b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    mem[Blob.size()] = '\0';
569ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko    return mem;
57b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner  }
58153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek};
59153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
60153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
61153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
62153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Cleanup.
63153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
64153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
65153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXLoadedDiagnostic::~CXLoadedDiagnostic() {}
66153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
67153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
68153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Public CXLoadedDiagnostic methods.
69153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
70153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
71153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // FIXME: Fail more softly if the diagnostic level is unknown?
73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  auto severityAsLevel = static_cast<serialized_diags::Level>(severity);
74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(severity == static_cast<unsigned>(severityAsLevel) &&
75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         "unknown serialized diagnostic level");
76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  switch (severityAsLevel) {
78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#define CASE(X) case serialized_diags::X: return CXDiagnostic_##X;
79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Ignored)
80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Note)
81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Warning)
82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Error)
83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Fatal)
84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#undef CASE
856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // The 'Remark' level isn't represented in the stable API.
866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  case serialized_diags::Remark: return CXDiagnostic_Warning;
87153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
88153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
89153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm_unreachable("Invalid diagnostic level");
90153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
91153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
92153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
93153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
94153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
95153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  uintptr_t V = (uintptr_t) DLoc;
96153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  V |= 0x1;
97c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CXSourceLocation Loc = { {  (void*) V, nullptr }, 0 };
98153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Loc;
99153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
100153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
101153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceLocation CXLoadedDiagnostic::getLocation() const {
102153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
103153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
104153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return makeLocation(&DiagLoc);
105153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
106153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
107153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getSpelling() const {
1085595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  return cxstring::createRef(Spelling);
109153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
110153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
111153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
112153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (DiagOption.empty())
113dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko    return cxstring::createEmpty();
114153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
115153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // FIXME: possibly refactor with logic in CXStoredDiagnostic.
116153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Disable)
1175595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko    *Disable = cxstring::createDup((Twine("-Wno-") + DiagOption).str());
1185595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  return cxstring::createDup((Twine("-W") + DiagOption).str());
119153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
120153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
121153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getCategory() const {
122153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return category;
123153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
124153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
12578d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted KremenekCXString CXLoadedDiagnostic::getCategoryText() const {
1265595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  return cxstring::createDup(CategoryText);
12778d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek}
12878d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek
129153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumRanges() const {
130153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Ranges.size();
131153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
132153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
133153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
134153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert(Range < Ranges.size());
135153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Ranges[Range];
136153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
137153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
138153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumFixIts() const {
139153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return FixIts.size();
140153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
141153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
142153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
143153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      CXSourceRange *ReplacementRange) const {
144153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert(FixIt < FixIts.size());
145153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (ReplacementRange)
146153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *ReplacementRange = FixIts[FixIt].first;
1479ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  return cxstring::createRef(FixIts[FixIt].second);
148153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
149153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
150153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekvoid CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
151153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        CXFile *file,
152153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *line,
153153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *column,
154153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *offset) {
155153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
156153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
157153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // CXSourceLocation consists of the following fields:
158153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
159153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //   void *ptr_data[2];
160153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //   unsigned int_data;
161153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
162153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
163153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
164153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
165153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // For now, do the unoptimized approach and store the data in a side
166153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // data structure.  We can optimize this case later.
167153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
168153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  uintptr_t V = (uintptr_t) location.ptr_data[0];
169153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert((V & 0x1) == 1);
170153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  V &= ~(uintptr_t)1;
171153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
172153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  const Location &Loc = *((Location*)V);
173153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
174153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (file)
175153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *file = Loc.file;
176153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (line)
177153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *line = Loc.line;
178153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (column)
179153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *column = Loc.column;
180153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (offset)
181153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *offset = Loc.offset;
182153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
183153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
184153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
185153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Deserialize diagnostics.
186153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
187153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
188153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace {
189176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesclass DiagLoader : serialized_diags::SerializedDiagnosticReader {
190153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  enum CXLoadDiag_Error *error;
191153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXString *errorString;
192176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags;
193176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags;
194176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
195176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
196153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (error)
197153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      *error = code;
198153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (errorString)
1995595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko      *errorString = cxstring::createDup(err);
200176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return serialized_diags::SDError::HandlerFailed;
201153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
202153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
203176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code reportInvalidFile(llvm::StringRef err) {
204153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return reportBad(CXLoadDiag_InvalidFile, err);
205153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
206153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
207176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code readRange(const serialized_diags::Location &SDStart,
208176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            const serialized_diags::Location &SDEnd,
209176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            CXSourceRange &SR);
210e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek
211176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code readLocation(const serialized_diags::Location &SDLoc,
212176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                               CXLoadedDiagnostic::Location &LoadedLoc);
213153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
214176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesprotected:
215176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitStartOfDiagnostic() override;
216176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitEndOfDiagnostic() override;
217153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
218176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
219153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
220176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
221153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
222176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitDiagnosticRecord(
223176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      unsigned Severity, const serialized_diags::Location &Location,
224176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      unsigned Category, unsigned Flag, StringRef Message) override;
225153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
226176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                      unsigned Timestamp,
228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                      StringRef Name) override;
229176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code visitFixitRecord(const serialized_diags::Location &Start,
231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   const serialized_diags::Location &End,
232176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   StringRef CodeToInsert) override;
233176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
234176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code
235176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  visitSourceRangeRecord(const serialized_diags::Location &Start,
236176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         const serialized_diags::Location &End) override;
237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
238176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinespublic:
239176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
240176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      : SerializedDiagnosticReader(), error(e), errorString(es) {
241176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (error)
242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      *error = CXLoadDiag_None;
243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (errorString)
244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      *errorString = cxstring::createEmpty();
245153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXDiagnosticSet load(const char *file);
248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines};
249153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
250153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesCXDiagnosticSet DiagLoader::load(const char *file) {
252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>();
253176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
254176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code EC = readDiagnostics(file);
255176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (EC) {
256176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch (EC.value()) {
257176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case static_cast<int>(serialized_diags::SDError::HandlerFailed):
258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // We've already reported the problem.
259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      break;
260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case static_cast<int>(serialized_diags::SDError::CouldNotLoad):
261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      reportBad(CXLoadDiag_CannotLoad, EC.message());
262176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      break;
263176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    default:
264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      reportInvalidFile(EC.message());
265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      break;
266153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return 0;
268153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return (CXDiagnosticSet)TopDiags.release();
271153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
272153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code
274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::readLocation(const serialized_diags::Location &SDLoc,
275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         CXLoadedDiagnostic::Location &LoadedLoc) {
276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  unsigned FileID = SDLoc.FileID;
277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (FileID == 0)
278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    LoadedLoc.file = nullptr;
279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  else {
280176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    LoadedLoc.file = const_cast<FileEntry *>(TopDiags->Files[FileID]);
281176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!LoadedLoc.file)
282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return reportInvalidFile("Corrupted file entry in source location");
283153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
284176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  LoadedLoc.line = SDLoc.Line;
285176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  LoadedLoc.column = SDLoc.Col;
286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  LoadedLoc.offset = SDLoc.Offset;
287176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
288153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
289153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
290176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code
291176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::readRange(const serialized_diags::Location &SDStart,
292176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                      const serialized_diags::Location &SDEnd,
293176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                      CXSourceRange &SR) {
294176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXLoadedDiagnostic::Location *Start, *End;
295176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  Start = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
296176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  End = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
297176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
298176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code EC;
299176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if ((EC = readLocation(SDStart, *Start)))
300176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return EC;
301176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if ((EC = readLocation(SDEnd, *End)))
302176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return EC;
303153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
304176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXSourceLocation startLoc = makeLocation(Start);
305176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXSourceLocation endLoc = makeLocation(End);
306176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  SR = clang_getRange(startLoc, endLoc);
307176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
308176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
309952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek
310176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitStartOfDiagnostic() {
311176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CurrentDiags.push_back(llvm::make_unique<CXLoadedDiagnostic>());
312176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
313153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
314153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
315176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitEndOfDiagnostic() {
316176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto D = CurrentDiags.pop_back_val();
317176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (CurrentDiags.empty())
318176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    TopDiags->appendDiagnostic(std::move(D));
319176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  else
320176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    CurrentDiags.back()->getChildDiagnostics().appendDiagnostic(std::move(D));
321176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
322153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
323153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
324176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) {
325176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // FIXME: Why do we care about long strings?
326176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Name.size() > 65536)
327176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return reportInvalidFile("Out-of-bounds string in category");
328176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  TopDiags->Categories[ID] = TopDiags->copyString(Name);
329176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
330176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
331153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
332176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitDiagFlagRecord(unsigned ID, StringRef Name) {
333176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // FIXME: Why do we care about long strings?
334176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Name.size() > 65536)
335176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return reportInvalidFile("Out-of-bounds string in warning flag");
336176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  TopDiags->WarningFlags[ID] = TopDiags->copyString(Name);
337176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
338153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
339153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
340176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitFilenameRecord(unsigned ID, unsigned Size,
341176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                                unsigned Timestamp,
342176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                                StringRef Name) {
343176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // FIXME: Why do we care about long strings?
344176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Name.size() > 65536)
345176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return reportInvalidFile("Out-of-bounds string in filename");
346176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  TopDiags->FileNames[ID] = TopDiags->copyString(Name);
347176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  TopDiags->Files[ID] =
348176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      TopDiags->FakeFiles.getVirtualFile(Name, Size, Timestamp);
349176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
350153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
351153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
352176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code
353176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start,
354176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                   const serialized_diags::Location &End) {
355176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXSourceRange SR;
356176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (std::error_code EC = readRange(Start, End, SR))
357176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return EC;
358176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CurrentDiags.back()->Ranges.push_back(SR);
359176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
360176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
361153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
362176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code
363176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::visitFixitRecord(const serialized_diags::Location &Start,
364176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                             const serialized_diags::Location &End,
365176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                             StringRef CodeToInsert) {
366176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXSourceRange SR;
367176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (std::error_code EC = readRange(Start, End, SR))
368176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return EC;
369176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // FIXME: Why do we care about long strings?
370176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (CodeToInsert.size() > 65536)
371176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return reportInvalidFile("Out-of-bounds string in FIXIT");
372176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CurrentDiags.back()->FixIts.push_back(
373176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      std::make_pair(SR, TopDiags->copyString(CodeToInsert)));
374176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
375176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
377176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitDiagnosticRecord(
378176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned Severity, const serialized_diags::Location &Location,
379176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned Category, unsigned Flag, StringRef Message) {
380176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CXLoadedDiagnostic &D = *CurrentDiags.back();
381176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  D.severity = Severity;
382176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (std::error_code EC = readLocation(Location, D.DiagLoc))
383176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return EC;
384176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  D.category = Category;
385176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : "";
386176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  D.CategoryText = Category ? TopDiags->Categories[Category] : "";
387176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  D.Spelling = TopDiags->copyString(Message);
388176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
389153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
390153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
391153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekextern "C" {
392153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSet clang_loadDiagnostics(const char *file,
393153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      enum CXLoadDiag_Error *error,
394153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      CXString *errorString) {
395153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  DiagLoader L(error, errorString);
396153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return L.load(file);
397153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
398153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} // end extern 'C'.
399