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"
19153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Frontend/SerializedDiagnosticPrinter.h"
20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/Optional.h"
21153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/StringRef.h"
22153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/Twine.h"
23153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Bitcode/BitstreamReader.h"
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/ErrorHandling.h"
25153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Support/MemoryBuffer.h"
26153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekusing namespace clang;
27153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
28153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
29153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
30153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
31153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
329ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenkotypedef llvm::DenseMap<unsigned, const char *> Strings;
33153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
34153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace {
35153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekclass CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
36153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekpublic:
37153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
38153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  virtual ~CXLoadedDiagnosticSetImpl() {}
39153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
40153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BumpPtrAllocator Alloc;
41153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings Categories;
42153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings WarningFlags;
43153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings FileNames;
44153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
45153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileSystemOptions FO;
46153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileManager FakeFiles;
47153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::DenseMap<unsigned, const FileEntry *> Files;
489ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko
499ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  /// \brief Copy the string into our own allocator.
509ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  const char *copyString(StringRef Blob) {
51b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    char *mem = Alloc.Allocate<char>(Blob.size() + 1);
52b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    memcpy(mem, Blob.data(), Blob.size());
53b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    mem[Blob.size()] = '\0';
549ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko    return mem;
55b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner  }
56153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek};
57153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
58153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
59153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
60153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Cleanup.
61153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
62153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
63153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXLoadedDiagnostic::~CXLoadedDiagnostic() {}
64153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
65153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
66153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Public CXLoadedDiagnostic methods.
67153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
68153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
69153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // FIXME: Fail more softly if the diagnostic level is unknown?
71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  auto severityAsLevel = static_cast<serialized_diags::Level>(severity);
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(severity == static_cast<unsigned>(severityAsLevel) &&
73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines         "unknown serialized diagnostic level");
74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  switch (severityAsLevel) {
76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#define CASE(X) case serialized_diags::X: return CXDiagnostic_##X;
77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Ignored)
78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Note)
79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Warning)
80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Error)
81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  CASE(Fatal)
82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#undef CASE
836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // The 'Remark' level isn't represented in the stable API.
846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  case serialized_diags::Remark: return CXDiagnostic_Warning;
85153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
86153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
87153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm_unreachable("Invalid diagnostic level");
88153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
89153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
90153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
91153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
92153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
93153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  uintptr_t V = (uintptr_t) DLoc;
94153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  V |= 0x1;
95ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  CXSourceLocation Loc = { {  (void*) V, nullptr }, 0 };
96153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Loc;
97153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
98153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
99153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceLocation CXLoadedDiagnostic::getLocation() const {
100153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
101153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
102153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return makeLocation(&DiagLoc);
103153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
104153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
105153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getSpelling() const {
1065595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  return cxstring::createRef(Spelling);
107153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
108153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
109153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
110153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (DiagOption.empty())
111dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko    return cxstring::createEmpty();
112153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
113153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // FIXME: possibly refactor with logic in CXStoredDiagnostic.
114153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Disable)
1155595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko    *Disable = cxstring::createDup((Twine("-Wno-") + DiagOption).str());
1165595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  return cxstring::createDup((Twine("-W") + DiagOption).str());
117153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
118153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
119153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getCategory() const {
120153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return category;
121153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
122153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
12378d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted KremenekCXString CXLoadedDiagnostic::getCategoryText() const {
1245595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  return cxstring::createDup(CategoryText);
12578d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek}
12678d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek
127153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumRanges() const {
128153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Ranges.size();
129153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
130153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
131153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
132153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert(Range < Ranges.size());
133153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Ranges[Range];
134153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
135153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
136153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumFixIts() const {
137153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return FixIts.size();
138153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
139153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
140153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
141153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      CXSourceRange *ReplacementRange) const {
142153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert(FixIt < FixIts.size());
143153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (ReplacementRange)
144153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *ReplacementRange = FixIts[FixIt].first;
1459ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  return cxstring::createRef(FixIts[FixIt].second);
146153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
147153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
148153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekvoid CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
149153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        CXFile *file,
150153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *line,
151153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *column,
152153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *offset) {
153153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
154153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
155153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // CXSourceLocation consists of the following fields:
156153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
157153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //   void *ptr_data[2];
158153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //   unsigned int_data;
159153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
160153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
161153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
162153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
163153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // For now, do the unoptimized approach and store the data in a side
164153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // data structure.  We can optimize this case later.
165153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
166153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  uintptr_t V = (uintptr_t) location.ptr_data[0];
167153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert((V & 0x1) == 1);
168153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  V &= ~(uintptr_t)1;
169153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
170153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  const Location &Loc = *((Location*)V);
171153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
172153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (file)
173153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *file = Loc.file;
174153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (line)
175153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *line = Loc.line;
176153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (column)
177153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *column = Loc.column;
178153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (offset)
179153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *offset = Loc.offset;
180153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
181153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
182153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
183153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Deserialize diagnostics.
184153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
185153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesenum { MaxSupportedVersion = 2 };
187153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenektypedef SmallVector<uint64_t, 64> RecordData;
188153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekenum LoadResult { Failure = 1, Success = 0 };
189153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekenum StreamResult { Read_EndOfStream,
190153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_BlockBegin,
191153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_Failure,
192153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_Record,
193153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_BlockEnd };
194153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
195153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace {
196153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekclass DiagLoader {
197153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  enum CXLoadDiag_Error *error;
198153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXString *errorString;
199153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
200153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
201153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (error)
202153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      *error = code;
203153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (errorString)
2045595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko      *errorString = cxstring::createDup(err);
205153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
206153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
207153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  void reportInvalidFile(llvm::StringRef err) {
208153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return reportBad(CXLoadDiag_InvalidFile, err);
209153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
210153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
211153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readMetaBlock(llvm::BitstreamCursor &Stream);
212153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
213153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream,
214153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 CXDiagnosticSetImpl &Diags,
215153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 CXLoadedDiagnosticSetImpl &TopDiags);
216153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
217153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
218153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       llvm::StringRef errorContext,
219153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       unsigned &BlockOrRecordID,
220e485f0761abc7ead2d0481db37fd50f5ae2e835bChris Lattner                                       bool atTopLevel = false);
221153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
222153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
223153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
224153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        Strings &strings, llvm::StringRef errorContext,
225153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        RecordData &Record,
226b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                        StringRef Blob,
227952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                        bool allowEmptyString = false);
228153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
229153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
2309ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko                        const char *&RetStr,
231153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        llvm::StringRef errorContext,
232153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        RecordData &Record,
233b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                        StringRef Blob,
234952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                        bool allowEmptyString = false);
235153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
236153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags,
237153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       RecordData &Record, unsigned RecStartIdx,
238153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       CXSourceRange &SR);
239153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
240153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
241153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          RecordData &Record, unsigned &offset,
242153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          CXLoadedDiagnostic::Location &Loc);
243153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
244153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekpublic:
245153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
246153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    : error(e), errorString(es) {
247153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (error)
248153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        *error = CXLoadDiag_None;
249153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (errorString)
250dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko        *errorString = cxstring::createEmpty();
251153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
252e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek
253153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXDiagnosticSet load(const char *file);
254153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek};
255153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
256153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
257153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSet DiagLoader::load(const char *file) {
258153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // Open the diagnostics file.
259153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  std::string ErrStr;
260153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileSystemOptions FO;
261153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileManager FileMgr(FO);
262153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<llvm::MemoryBuffer> Buffer;
264153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Buffer.reset(FileMgr.getBufferForFile(file));
265153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
266153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (!Buffer) {
267153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportBad(CXLoadDiag_CannotLoad, ErrStr);
268ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return nullptr;
269153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
270153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
271153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BitstreamReader StreamFile;
272153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
273153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                  (const unsigned char *)Buffer->getBufferEnd());
274153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
275153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BitstreamCursor Stream;
276153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Stream.init(StreamFile);
277153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
278153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // Sniff for the signature.
279153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Stream.Read(8) != 'D' ||
280153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      Stream.Read(8) != 'I' ||
281153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      Stream.Read(8) != 'A' ||
282153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      Stream.Read(8) != 'G') {
283153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportBad(CXLoadDiag_InvalidFile,
284153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek              "Bad header in diagnostics file");
285ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return nullptr;
286153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
287153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<CXLoadedDiagnosticSetImpl> Diags(
289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new CXLoadedDiagnosticSetImpl());
290153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
291153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (true) {
292153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned BlockID = 0;
293153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",
294153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                               BlockID, true);
295153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch (Res) {
296153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_EndOfStream:
297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return (CXDiagnosticSet)Diags.release();
298153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Failure:
299ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        return nullptr;
300153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Record:
301153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm_unreachable("Top-level does not have records");
302153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockEnd:
303153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
304153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockBegin:
305153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
306153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
307153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
308153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch (BlockID) {
309153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::BLOCK_META:
310153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readMetaBlock(Stream))
311ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          return nullptr;
312153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
313153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::BLOCK_DIAG:
314153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get()))
315ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          return nullptr;
316153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
317153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      default:
318153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (!Stream.SkipBlock()) {
319153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Malformed block at top-level of diagnostics file");
320ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          return nullptr;
321153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
322153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
323153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
324153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
325153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
326153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
327153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekStreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
328153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                                 llvm::StringRef errorContext,
329153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                                 unsigned &blockOrRecordID,
330e485f0761abc7ead2d0481db37fd50f5ae2e835bChris Lattner                                                 bool atTopLevel) {
331153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
332153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  blockOrRecordID = 0;
333153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
334153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (!Stream.AtEndOfStream()) {
335153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned Code = Stream.ReadCode();
336153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
337153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    // Handle the top-level specially.
338153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (atTopLevel) {
339153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
340153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        unsigned BlockID = Stream.ReadSubBlockID();
341153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
342153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          if (Stream.ReadBlockInfoBlock()) {
343153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            reportInvalidFile("Malformed BlockInfoBlock in diagnostics file");
344153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            return Read_Failure;
345153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          }
346153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          continue;
347153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
348153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        blockOrRecordID = BlockID;
349153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_BlockBegin;
350153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
351153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      reportInvalidFile("Only blocks can appear at the top of a "
352153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        "diagnostic file");
353153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      return Read_Failure;
354153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
355153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
356153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch ((llvm::bitc::FixedAbbrevIDs)Code) {
357153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::ENTER_SUBBLOCK:
358153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        blockOrRecordID = Stream.ReadSubBlockID();
359153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_BlockBegin;
360153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
361153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::END_BLOCK:
362153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (Stream.ReadBlockEnd()) {
363153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Cannot read end of block");
364153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Read_Failure;
365153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
366153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_BlockEnd;
367153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
368153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::DEFINE_ABBREV:
369153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        Stream.ReadAbbrevRecord();
370153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
371153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
372153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::UNABBREV_RECORD:
373153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        reportInvalidFile("Diagnostics file should have no unabbreviated "
374153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          "records");
375153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_Failure;
376153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
377153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      default:
378153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        // We found a record.
379153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        blockOrRecordID = Code;
380153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_Record;
381153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
382153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
383153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
384153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (atTopLevel)
385153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Read_EndOfStream;
386153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
387153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
388153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    errorContext.str());
389153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Read_Failure;
390153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
391153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
392153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) {
393153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
394153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("Malformed metadata block");
395153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
396153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
397153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
398153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  bool versionChecked = false;
399153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
400153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (true) {
401153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned blockOrCode = 0;
402153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block",
403153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                               blockOrCode);
404153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
405153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch(Res) {
406153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_EndOfStream:
407153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock");
408153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Failure:
409153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
410153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Record:
411153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
412153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockBegin:
413153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (Stream.SkipBlock()) {
414153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Malformed metadata block");
415153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
416153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
417153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockEnd:
418153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (!versionChecked) {
419153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Diagnostics file does not contain version"
420153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                            " information");
421153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
422153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
423153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Success;
424153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
425153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
426153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    RecordData Record;
427b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    unsigned recordID = Stream.readRecord(blockOrCode, Record);
428153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
429153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (recordID == serialized_diags::RECORD_VERSION) {
430153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (Record.size() < 1) {
431153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        reportInvalidFile("malformed VERSION identifier in diagnostics file");
432153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
433153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
434153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (Record[0] > MaxSupportedVersion) {
435fc09336a5965040736f9bc63a70416003972364eStefanus Du Toit        reportInvalidFile("diagnostics file is a newer version than the one "
436153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          "supported");
437153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
438153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
439153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      versionChecked = true;
440153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
441153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
442153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
443153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
444153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
4459ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko                                  const char *&RetStr,
446153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  llvm::StringRef errorContext,
447153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  RecordData &Record,
448b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                                  StringRef Blob,
449952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                                  bool allowEmptyString) {
450153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
451153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // Basic buffer overflow check.
452b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner  if (Blob.size() > 65536) {
453153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile(std::string("Out-of-bounds string in ") +
454153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                      std::string(errorContext));
455153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
456153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
457952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek
458b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner  if (allowEmptyString && Record.size() >= 1 && Blob.size() == 0) {
459952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek    RetStr = "";
460952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek    return Success;
461952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek  }
462153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
463b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner  if (Record.size() < 1 || Blob.size() == 0) {
464153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile(std::string("Corrupted ") + std::string(errorContext)
465153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                      + std::string(" entry"));
466153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
467153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
468153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
4699ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  RetStr = TopDiags.copyString(Blob);
470153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
471153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
472153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
473153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
474153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  Strings &strings,
475153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  llvm::StringRef errorContext,
476153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  RecordData &Record,
477b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                                  StringRef Blob,
478952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                                  bool allowEmptyString) {
4799ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko  const char *RetStr;
480b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner  if (readString(TopDiags, RetStr, errorContext, Record, Blob,
481952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                 allowEmptyString))
482153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
483153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  strings[Record[0]] = RetStr;
484153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
485153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
486153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
487153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
488153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                    RecordData &Record, unsigned &offset,
489153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                    CXLoadedDiagnostic::Location &Loc) {
490153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Record.size() < offset + 3) {
491153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("Corrupted source location");
492153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
493153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
494153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
495153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  unsigned fileID = Record[offset++];
496153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (fileID == 0) {
497153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    // Sentinel value.
498ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Loc.file = nullptr;
499153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.line = 0;
500153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.column = 0;
501153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.offset = 0;
502153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Success;
503153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
504153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
505153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  const FileEntry *FE = TopDiags.Files[fileID];
506153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (!FE) {
507153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("Corrupted file entry in source location");
508153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
509153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
510527ce9fb91cc462abfe88843d3b8addf6c0f7365David Greene  Loc.file = const_cast<FileEntry *>(FE);
511153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.line = Record[offset++];
512153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.column = Record[offset++];
513153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.offset = Record[offset++];
514153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
515153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
516153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
517153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags,
518153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 RecordData &Record,
519153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 unsigned int RecStartIdx,
520153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 CXSourceRange &SR) {
521153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXLoadedDiagnostic::Location *Start, *End;
522153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
523153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
524153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
525153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (readLocation(TopDiags, Record, RecStartIdx, *Start))
526153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
527153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (readLocation(TopDiags, Record, RecStartIdx, *End))
528153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
529153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
530153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXSourceLocation startLoc = makeLocation(Start);
531153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXSourceLocation endLoc = makeLocation(End);
532153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  SR = clang_getRange(startLoc, endLoc);
533153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
534153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
535153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
536153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
537153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                           CXDiagnosticSetImpl &Diags,
538153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                           CXLoadedDiagnosticSetImpl &TopDiags){
539153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
540153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
541153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("malformed diagnostic block");
542153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
543153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
544651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic());
546153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  RecordData Record;
547153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
548153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (true) {
549153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned blockOrCode = 0;
550153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block",
551153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                               blockOrCode);
552153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch (Res) {
553153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_EndOfStream:
554153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock");
555153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Failure:
556153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
557153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockBegin: {
558153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        // The only blocks we care about are subdiagnostics.
559153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (blockOrCode != serialized_diags::BLOCK_DIAG) {
560153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          if (!Stream.SkipBlock()) {
561153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            reportInvalidFile("Invalid subblock in Diagnostics block");
562153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            return Failure;
563153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          }
564153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(),
565153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       TopDiags)) {
566153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
567153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
568153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
569153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
570153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
571153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockEnd:
572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Diags.appendDiagnostic(D.release());
573153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Success;
574153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Record:
575153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
576153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
577153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
578153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    // Read the record.
579153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Record.clear();
580b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    StringRef Blob;
581b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner    unsigned recID = Stream.readRecord(blockOrCode, Record, &Blob);
582153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
583153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (recID < serialized_diags::RECORD_FIRST ||
584153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        recID > serialized_diags::RECORD_LAST)
585153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      continue;
586153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
587153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch ((serialized_diags::RecordIDs)recID) {
588153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_VERSION:
589153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
590153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_CATEGORY:
591153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readString(TopDiags, TopDiags.Categories, "category", Record,
592b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                       Blob, /* allowEmptyString */ true))
593153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
594153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
595153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
596153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_DIAG_FLAG:
597153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record,
598b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                       Blob))
599153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
600153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
601153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
602153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_FILENAME: {
603153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readString(TopDiags, TopDiags.FileNames, "filename", Record,
604b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner                       Blob))
605153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
606153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
607153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (Record.size() < 3) {
608153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Invalid file entry");
609153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
610153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
611153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
612153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        const FileEntry *FE =
613153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
614153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                            /* size */ Record[1],
615153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                            /* time */ Record[2]);
616153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
617153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        TopDiags.Files[Record[0]] = FE;
618153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
619153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
620153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
621153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_SOURCE_RANGE: {
622153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        CXSourceRange SR;
623153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readRange(TopDiags, Record, 0, SR))
624153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
625153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->Ranges.push_back(SR);
626153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
627153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
628153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
629153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_FIXIT: {
630153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        CXSourceRange SR;
631153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readRange(TopDiags, Record, 0, SR))
632153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
6339ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko        const char *RetStr;
634b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner        if (readString(TopDiags, RetStr, "FIXIT", Record, Blob,
635952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                       /* allowEmptyString */ true))
636153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
6379ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko        D->FixIts.push_back(std::make_pair(SR, RetStr));
638e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek        continue;
639153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
640153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
641153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_DIAG: {
642153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->severity = Record[0];
643153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        unsigned offset = 1;
644153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readLocation(TopDiags, Record, offset, D->DiagLoc))
645153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
646153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->category = Record[offset++];
647153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        unsigned diagFlag = Record[offset++];
648153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : "";
64978d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek        D->CategoryText = D->category ? TopDiags.Categories[D->category] : "";
6509ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko        D->Spelling = TopDiags.copyString(Blob);
651153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
652153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
653153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
654153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
655153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
656153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
657153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekextern "C" {
658153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSet clang_loadDiagnostics(const char *file,
659153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      enum CXLoadDiag_Error *error,
660153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      CXString *errorString) {
661153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  DiagLoader L(error, errorString);
662153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return L.load(file);
663153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
664153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} // end extern 'C'.
665