1153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek/*===-- CXLoadedDiagnostic.cpp - Handling of persisent diags -*- C++ -*-===*\
2153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*                                                                            *|
3153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*                     The LLVM Compiler Infrastructure                       *|
4153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*                                                                            *|
5153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|* This file is distributed under the University of Illinois Open Source      *|
6153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|* License. See LICENSE.TXT for details.                                      *|
7153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*                                                                            *|
8153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*===----------------------------------------------------------------------===*|
9153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*                                                                            *|
10153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|* Implements handling of persisent diagnostics.                              *|
11153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek|*                                                                            *|
12153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek\*===----------------------------------------------------------------------===*/
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"
18153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Frontend/SerializedDiagnosticPrinter.h"
19153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/StringRef.h"
20153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/Twine.h"
21153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/Optional.h"
22153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Basic/LLVM.h"
23153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Support/ErrorHandling.h"
24153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Bitcode/BitstreamReader.h"
25153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Support/MemoryBuffer.h"
26153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include <assert.h>
27153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
28153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekusing namespace clang;
29153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekusing namespace clang::cxstring;
30153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
31153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
32153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
33153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
34153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
35153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenektypedef llvm::DenseMap<unsigned, llvm::StringRef> Strings;
36153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
37153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace {
38153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekclass CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
39153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekpublic:
40153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
41153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  virtual ~CXLoadedDiagnosticSetImpl() {}
42153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
43153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::StringRef makeString(const char *blob, unsigned blobLen);
44153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
45153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BumpPtrAllocator Alloc;
46153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings Categories;
47153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings WarningFlags;
48153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Strings FileNames;
49153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
50153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileSystemOptions FO;
51153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileManager FakeFiles;
52153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::DenseMap<unsigned, const FileEntry *> Files;
53153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek};
54153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
55153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
56153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekllvm::StringRef CXLoadedDiagnosticSetImpl::makeString(const char *blob,
57153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                                      unsigned bloblen) {
58e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek  char *mem = Alloc.Allocate<char>(bloblen + 1);
59153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  memcpy(mem, blob, bloblen);
60e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek  // Add a null terminator for those clients accessing the buffer
61e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek  // like a c-string.
62e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek  mem[bloblen] = '\0';
63153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return llvm::StringRef(mem, bloblen);
64153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
65153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
66153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
67153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Cleanup.
68153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
69153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
70153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXLoadedDiagnostic::~CXLoadedDiagnostic() {}
71153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
72153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
73153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Public CXLoadedDiagnostic methods.
74153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
75153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
76153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
77153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // FIXME: possibly refactor with logic in CXStoredDiagnostic.
78153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  switch (severity) {
79153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
80153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case DiagnosticsEngine::Note:    return CXDiagnostic_Note;
81153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
82153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case DiagnosticsEngine::Error:   return CXDiagnostic_Error;
83153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    case DiagnosticsEngine::Fatal:   return CXDiagnostic_Fatal;
84153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
85153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
86153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm_unreachable("Invalid diagnostic level");
87153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
88153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
89153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
90153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
91153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
92153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  uintptr_t V = (uintptr_t) DLoc;
93153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  V |= 0x1;
94153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXSourceLocation Loc = { {  (void*) V, 0 }, 0 };
95153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Loc;
96153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
97153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
98153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceLocation CXLoadedDiagnostic::getLocation() const {
99153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
100153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
101153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return makeLocation(&DiagLoc);
102153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
103153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
104153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getSpelling() const {
105e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek  return cxstring::createCXString(Spelling, false);
106153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
107153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
108153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
109153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (DiagOption.empty())
110153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return createCXString("");
111153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
112153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // FIXME: possibly refactor with logic in CXStoredDiagnostic.
113153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Disable)
114153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *Disable = createCXString((Twine("-Wno-") + DiagOption).str());
115153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return createCXString((Twine("-W") + DiagOption).str());
116153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
117153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
118153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getCategory() const {
119153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return category;
120153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
121153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
12278d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted KremenekCXString CXLoadedDiagnostic::getCategoryText() const {
12378d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek  return cxstring::createCXString(CategoryText);
12478d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek}
12578d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek
126153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumRanges() const {
127153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Ranges.size();
128153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
129153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
130153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
131153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert(Range < Ranges.size());
132153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Ranges[Range];
133153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
134153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
135153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumFixIts() const {
136153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return FixIts.size();
137153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
138153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
139153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
140153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      CXSourceRange *ReplacementRange) const {
141153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert(FixIt < FixIts.size());
142153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (ReplacementRange)
143153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *ReplacementRange = FixIts[FixIt].first;
144153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return FixIts[FixIt].second;
145153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
146153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
147153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekvoid CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
148153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        CXFile *file,
149153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *line,
150153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *column,
151153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                        unsigned int *offset) {
152153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
153153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
154153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // CXSourceLocation consists of the following fields:
155153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
156153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //   void *ptr_data[2];
157153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //   unsigned int_data;
158153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
159153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // The lowest bit of ptr_data[0] is always set to 1 to indicate this
160153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // is a persistent diagnostic.
161153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  //
162153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // For now, do the unoptimized approach and store the data in a side
163153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // data structure.  We can optimize this case later.
164153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
165153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  uintptr_t V = (uintptr_t) location.ptr_data[0];
166153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  assert((V & 0x1) == 1);
167153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  V &= ~(uintptr_t)1;
168153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
169153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  const Location &Loc = *((Location*)V);
170153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
171153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (file)
172153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *file = Loc.file;
173153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (line)
174153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *line = Loc.line;
175153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (column)
176153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *column = Loc.column;
177153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (offset)
178153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    *offset = Loc.offset;
179153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
180153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
181153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
182153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Deserialize diagnostics.
183153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===//
184153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
185153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekenum { MaxSupportedVersion = 1 };
186153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenektypedef SmallVector<uint64_t, 64> RecordData;
187153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekenum LoadResult { Failure = 1, Success = 0 };
188153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekenum StreamResult { Read_EndOfStream,
189153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_BlockBegin,
190153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_Failure,
191153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_Record,
192153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    Read_BlockEnd };
193153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
194153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace {
195153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekclass DiagLoader {
196153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  enum CXLoadDiag_Error *error;
197153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXString *errorString;
198153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
199153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
200153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (error)
201153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      *error = code;
202153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (errorString)
203153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      *errorString = createCXString(err);
204153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
205153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
206153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  void reportInvalidFile(llvm::StringRef err) {
207153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return reportBad(CXLoadDiag_InvalidFile, err);
208153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
209153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
210153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readMetaBlock(llvm::BitstreamCursor &Stream);
211153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
212153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream,
213153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 CXDiagnosticSetImpl &Diags,
214153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 CXLoadedDiagnosticSetImpl &TopDiags);
215153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
216153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
217153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       llvm::StringRef errorContext,
218153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       unsigned &BlockOrRecordID,
219153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       const bool atTopLevel = false);
220153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
221153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
222153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
223153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        Strings &strings, llvm::StringRef errorContext,
224153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        RecordData &Record,
225153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        const char *BlobStart,
226952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                        unsigned BlobLen,
227952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                        bool allowEmptyString = false);
228153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
229153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
230153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        llvm::StringRef &RetStr,
231153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        llvm::StringRef errorContext,
232153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        RecordData &Record,
233153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        const char *BlobStart,
234952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                        unsigned BlobLen,
235952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                        bool allowEmptyString = false);
236153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
237153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags,
238153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       RecordData &Record, unsigned RecStartIdx,
239153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       CXSourceRange &SR);
240153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
241153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
242153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          RecordData &Record, unsigned &offset,
243153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          CXLoadedDiagnostic::Location &Loc);
244153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
245153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekpublic:
246153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
247153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    : error(e), errorString(es) {
248153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (error)
249153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        *error = CXLoadDiag_None;
250153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (errorString)
251153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        *errorString = createCXString("");
252153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
253e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek
254153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXDiagnosticSet load(const char *file);
255153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek};
256153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
257153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
258153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSet DiagLoader::load(const char *file) {
259153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // Open the diagnostics file.
260153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  std::string ErrStr;
261153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileSystemOptions FO;
262153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  FileManager FileMgr(FO);
263153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2641e4c01b79273b9cd4e9e9ecfd3422df3900b8356Dylan Noblesmith  OwningPtr<llvm::MemoryBuffer> Buffer;
265153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Buffer.reset(FileMgr.getBufferForFile(file));
266153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
267153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (!Buffer) {
268153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportBad(CXLoadDiag_CannotLoad, ErrStr);
269153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return 0;
270153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
271153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
272153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BitstreamReader StreamFile;
273153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
274153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                  (const unsigned char *)Buffer->getBufferEnd());
275153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
276153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::BitstreamCursor Stream;
277153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Stream.init(StreamFile);
278153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
279153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // Sniff for the signature.
280153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Stream.Read(8) != 'D' ||
281153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      Stream.Read(8) != 'I' ||
282153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      Stream.Read(8) != 'A' ||
283153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      Stream.Read(8) != 'G') {
284153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportBad(CXLoadDiag_InvalidFile,
285153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek              "Bad header in diagnostics file");
286153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return 0;
287153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
288153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
2891e4c01b79273b9cd4e9e9ecfd3422df3900b8356Dylan Noblesmith  OwningPtr<CXLoadedDiagnosticSetImpl>
290153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Diags(new CXLoadedDiagnosticSetImpl());
291153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
292153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (true) {
293153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned BlockID = 0;
294153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",
295153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                               BlockID, true);
296153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch (Res) {
297153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_EndOfStream:
298153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return (CXDiagnosticSet) Diags.take();
299153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Failure:
300153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return 0;
301153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Record:
302153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm_unreachable("Top-level does not have records");
303153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockEnd:
304153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
305153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockBegin:
306153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
307153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
308153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
309153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch (BlockID) {
310153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::BLOCK_META:
311153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readMetaBlock(Stream))
312153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return 0;
313153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
314153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::BLOCK_DIAG:
315153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get()))
316153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return 0;
317153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
318153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      default:
319153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (!Stream.SkipBlock()) {
320153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Malformed block at top-level of diagnostics file");
321153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return 0;
322153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
323153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
324153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
325153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
326153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
327153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
328153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekStreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
329153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                                 llvm::StringRef errorContext,
330153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                                 unsigned &blockOrRecordID,
331153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                                 const bool atTopLevel) {
332153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
333153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  blockOrRecordID = 0;
334153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
335153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (!Stream.AtEndOfStream()) {
336153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned Code = Stream.ReadCode();
337153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
338153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    // Handle the top-level specially.
339153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (atTopLevel) {
340153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (Code == llvm::bitc::ENTER_SUBBLOCK) {
341153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        unsigned BlockID = Stream.ReadSubBlockID();
342153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
343153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          if (Stream.ReadBlockInfoBlock()) {
344153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            reportInvalidFile("Malformed BlockInfoBlock in diagnostics file");
345153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            return Read_Failure;
346153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          }
347153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          continue;
348153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
349153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        blockOrRecordID = BlockID;
350153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_BlockBegin;
351153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
352153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      reportInvalidFile("Only blocks can appear at the top of a "
353153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                        "diagnostic file");
354153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      return Read_Failure;
355153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
356153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
357153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch ((llvm::bitc::FixedAbbrevIDs)Code) {
358153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::ENTER_SUBBLOCK:
359153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        blockOrRecordID = Stream.ReadSubBlockID();
360153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_BlockBegin;
361153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
362153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::END_BLOCK:
363153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (Stream.ReadBlockEnd()) {
364153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Cannot read end of block");
365153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Read_Failure;
366153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
367153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_BlockEnd;
368153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
369153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::DEFINE_ABBREV:
370153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        Stream.ReadAbbrevRecord();
371153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
372153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
373153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case llvm::bitc::UNABBREV_RECORD:
374153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        reportInvalidFile("Diagnostics file should have no unabbreviated "
375153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          "records");
376153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_Failure;
377153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
378153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      default:
379153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        // We found a record.
380153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        blockOrRecordID = Code;
381153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Read_Record;
382153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
383153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
384153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
385153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (atTopLevel)
386153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Read_EndOfStream;
387153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
388153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
389153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                    errorContext.str());
390153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Read_Failure;
391153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
392153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
393153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) {
394153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
395153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("Malformed metadata block");
396153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
397153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
398153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
399153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  bool versionChecked = false;
400153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
401153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (true) {
402153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned blockOrCode = 0;
403153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block",
404153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                               blockOrCode);
405153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
406153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch(Res) {
407153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_EndOfStream:
408153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock");
409153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Failure:
410153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
411153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Record:
412153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
413153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockBegin:
414153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (Stream.SkipBlock()) {
415153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Malformed metadata block");
416153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
417153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
418153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockEnd:
419153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (!versionChecked) {
420153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Diagnostics file does not contain version"
421153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                            " information");
422153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
423153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
424153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Success;
425153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
426153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
427153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    RecordData Record;
428153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    const char *Blob;
429153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned BlobLen;
430153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned recordID = Stream.ReadRecord(blockOrCode, Record, &Blob, &BlobLen);
431153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
432153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (recordID == serialized_diags::RECORD_VERSION) {
433153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (Record.size() < 1) {
434153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        reportInvalidFile("malformed VERSION identifier in diagnostics file");
435153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
436153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
437153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      if (Record[0] > MaxSupportedVersion) {
438153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        reportInvalidFile("diagnosics file is a newer version than the one "
439153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                          "supported");
440153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
441153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
442153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      versionChecked = true;
443153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
444153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
445153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
446153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
447153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
448153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  llvm::StringRef &RetStr,
449153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  llvm::StringRef errorContext,
450153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  RecordData &Record,
451153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  const char *BlobStart,
452952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                                  unsigned BlobLen,
453952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                                  bool allowEmptyString) {
454153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
455153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  // Basic buffer overflow check.
456153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (BlobLen > 65536) {
457153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile(std::string("Out-of-bounds string in ") +
458153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                      std::string(errorContext));
459153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
460153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
461952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek
462952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek  if (allowEmptyString && Record.size() >= 1 && BlobLen == 0) {
463952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek    RetStr = "";
464952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek    return Success;
465952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek  }
466153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
467153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Record.size() < 1 || BlobLen == 0) {
468153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile(std::string("Corrupted ") + std::string(errorContext)
469153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                      + std::string(" entry"));
470153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
471153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
472153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
473153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  RetStr = TopDiags.makeString(BlobStart, BlobLen);
474153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
475153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
476153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
477153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
478153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  Strings &strings,
479153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  llvm::StringRef errorContext,
480153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  RecordData &Record,
481153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  const char *BlobStart,
482952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                                  unsigned BlobLen,
483952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                                  bool allowEmptyString) {
484153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  llvm::StringRef RetStr;
485952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek  if (readString(TopDiags, RetStr, errorContext, Record, BlobStart, BlobLen,
486952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                 allowEmptyString))
487153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
488153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  strings[Record[0]] = RetStr;
489153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
490153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
491153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
492153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
493153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                    RecordData &Record, unsigned &offset,
494153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                    CXLoadedDiagnostic::Location &Loc) {
495153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Record.size() < offset + 3) {
496153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("Corrupted source location");
497153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
498153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
499153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
500153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  unsigned fileID = Record[offset++];
501153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (fileID == 0) {
502153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    // Sentinel value.
503153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.file = 0;
504153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.line = 0;
505153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.column = 0;
506153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Loc.offset = 0;
507153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Success;
508153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
509153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
510153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  const FileEntry *FE = TopDiags.Files[fileID];
511153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (!FE) {
512153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("Corrupted file entry in source location");
513153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
514153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
515153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.file = (void*) FE;
516153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.line = Record[offset++];
517153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.column = Record[offset++];
518153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Loc.offset = Record[offset++];
519153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
520153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
521153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
522153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags,
523153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 RecordData &Record,
524153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 unsigned int RecStartIdx,
525153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                 CXSourceRange &SR) {
526153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXLoadedDiagnostic::Location *Start, *End;
527153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
528153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
529153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
530153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (readLocation(TopDiags, Record, RecStartIdx, *Start))
531153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
532153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (readLocation(TopDiags, Record, RecStartIdx, *End))
533153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
534153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
535153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXSourceLocation startLoc = makeLocation(Start);
536153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  CXSourceLocation endLoc = makeLocation(End);
537153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  SR = clang_getRange(startLoc, endLoc);
538153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return Success;
539153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
540153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
541153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekLoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
542153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                           CXDiagnosticSetImpl &Diags,
543153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                           CXLoadedDiagnosticSetImpl &TopDiags){
544153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
545153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
546153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    reportInvalidFile("malformed diagnostic block");
547153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    return Failure;
548153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
549153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
5501e4c01b79273b9cd4e9e9ecfd3422df3900b8356Dylan Noblesmith  OwningPtr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic());
551153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  RecordData Record;
552153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
553153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  while (true) {
554153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned blockOrCode = 0;
555153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block",
556153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                               blockOrCode);
557153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch (Res) {
558153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_EndOfStream:
559153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock");
560153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Failure:
561153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Failure;
562153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockBegin: {
563153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        // The only blocks we care about are subdiagnostics.
564153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (blockOrCode != serialized_diags::BLOCK_DIAG) {
565153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          if (!Stream.SkipBlock()) {
566153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            reportInvalidFile("Invalid subblock in Diagnostics block");
567153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek            return Failure;
568153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          }
569153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(),
570153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       TopDiags)) {
571153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
572153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
573153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
574153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
575153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
576153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_BlockEnd:
577153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        Diags.appendDiagnostic(D.take());
578153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        return Success;
579153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case Read_Record:
580153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        break;
581153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
582153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
583153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    // Read the record.
584153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Record.clear();
585153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    const char *BlobStart = 0;
586153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned BlobLen = 0;
587153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    unsigned recID = Stream.ReadRecord(blockOrCode, Record,
588153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                       BlobStart, BlobLen);
589153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
590153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    if (recID < serialized_diags::RECORD_FIRST ||
591153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        recID > serialized_diags::RECORD_LAST)
592153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      continue;
593153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
594153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    switch ((serialized_diags::RecordIDs)recID) {
595153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_VERSION:
596153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
597153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_CATEGORY:
598153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readString(TopDiags, TopDiags.Categories, "category", Record,
59913eee196469596a107762606e5cea6511368a54cTed Kremenek                       BlobStart, BlobLen,
60013eee196469596a107762606e5cea6511368a54cTed Kremenek                       /* allowEmptyString */ true))
601153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
602153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
603153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
604153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_DIAG_FLAG:
605153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record,
606153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       BlobStart, BlobLen))
607153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
608153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
609153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
610153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_FILENAME: {
611153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readString(TopDiags, TopDiags.FileNames, "filename", Record,
612153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       BlobStart, BlobLen))
613153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
614153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
615153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (Record.size() < 3) {
616153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          reportInvalidFile("Invalid file entry");
617153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
618153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        }
619153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
620153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        const FileEntry *FE =
621153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
622153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                            /* size */ Record[1],
623153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                            /* time */ Record[2]);
624153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
625153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        TopDiags.Files[Record[0]] = FE;
626153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
627153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
628153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
629153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_SOURCE_RANGE: {
630153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        CXSourceRange SR;
631153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readRange(TopDiags, Record, 0, SR))
632153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
633153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->Ranges.push_back(SR);
634153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
635153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
636153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
637153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_FIXIT: {
638153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        CXSourceRange SR;
639153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readRange(TopDiags, Record, 0, SR))
640153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
641153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        llvm::StringRef RetStr;
642952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek        if (readString(TopDiags, RetStr, "FIXIT", Record, BlobStart, BlobLen,
643952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek                       /* allowEmptyString */ true))
644153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
645e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek        D->FixIts.push_back(std::make_pair(SR, createCXString(RetStr, false)));
646e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek        continue;
647153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
648153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
649153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      case serialized_diags::RECORD_DIAG: {
650153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->severity = Record[0];
651153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        unsigned offset = 1;
652153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        if (readLocation(TopDiags, Record, offset, D->DiagLoc))
653153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek          return Failure;
654153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->category = Record[offset++];
655153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        unsigned diagFlag = Record[offset++];
656153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : "";
65778d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek        D->CategoryText = D->category ? TopDiags.Categories[D->category] : "";
658153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        D->Spelling = TopDiags.makeString(BlobStart, BlobLen);
659153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek        continue;
660153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek      }
661153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    }
662153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
663153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
664153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
665153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekextern "C" {
666153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSet clang_loadDiagnostics(const char *file,
667153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      enum CXLoadDiag_Error *error,
668153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                      CXString *errorString) {
669153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  DiagLoader L(error, errorString);
670153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  return L.load(file);
671153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}
672153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} // end extern 'C'.
673