17800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===//
27800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//
37800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//                     The LLVM Compiler Infrastructure
47800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//
57800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// This file is distributed under the University of Illinois Open Source
67800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// License. See LICENSE.TXT for details.
77800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//
87800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===//
97800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
1055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/SerializedDiagnosticPrinter.h"
1155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/Diagnostic.h"
1202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor#include "clang/Basic/DiagnosticOptions.h"
137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Basic/FileManager.h"
1455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h"
157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Basic/Version.h"
162a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek#include "clang/Frontend/DiagnosticRenderer.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Lexer.h"
1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/DenseSet.h"
1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallString.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/StringRef.h"
2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h"
2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include <vector>
237800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
247800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekusing namespace clang;
25fdd0ced001babd4e65fb909cc2f847df53faf764Ted Kremenekusing namespace clang::serialized_diags;
267800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
277800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace {
287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekclass AbbreviationMap {
307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  llvm::DenseMap<unsigned, unsigned> Abbrevs;
317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekpublic:
327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  AbbreviationMap() {}
337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  void set(unsigned recordID, unsigned abbrevID) {
357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    assert(Abbrevs.find(recordID) == Abbrevs.end()
367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek           && "Abbreviation already set.");
377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    Abbrevs[recordID] = abbrevID;
387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  }
397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  unsigned get(unsigned recordID) {
417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    assert(Abbrevs.find(recordID) != Abbrevs.end() &&
427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek           "Abbreviation not set.");
437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    return Abbrevs[recordID];
447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  }
457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek};
467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
47cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenkotypedef SmallVector<uint64_t, 64> RecordData;
48cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenkotypedef SmallVectorImpl<uint64_t> RecordDataImpl;
492a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
502a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekclass SDiagsWriter;
512a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
528be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass SDiagsRenderer : public DiagnosticNoteRenderer {
532a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  SDiagsWriter &Writer;
542a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekpublic:
55db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  SDiagsRenderer(SDiagsWriter &Writer, const LangOptions &LangOpts,
5602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor                 DiagnosticOptions *DiagOpts)
57db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    : DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
582a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
592a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  virtual ~SDiagsRenderer() {}
602a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
612a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekprotected:
622a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  virtual void emitDiagnosticMessage(SourceLocation Loc,
632a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                     PresumedLoc PLoc,
642a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                     DiagnosticsEngine::Level Level,
652a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                     StringRef Message,
662a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                     ArrayRef<CharSourceRange> Ranges,
6716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                     const SourceManager *SM,
688be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                     DiagOrStoredDiag D);
692a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
702a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
712a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                 DiagnosticsEngine::Level Level,
7216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                 ArrayRef<CharSourceRange> Ranges,
7316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                 const SourceManager &SM) {}
74db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
75db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  virtual void emitNote(SourceLocation Loc, StringRef Message,
76db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                        const SourceManager *SM);
77db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
782a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  virtual void emitCodeContext(SourceLocation Loc,
792a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                               DiagnosticsEngine::Level Level,
802a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                               SmallVectorImpl<CharSourceRange>& Ranges,
8116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                               ArrayRef<FixItHint> Hints,
8216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                               const SourceManager &SM);
83db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
848be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void beginDiagnostic(DiagOrStoredDiag D,
852a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                               DiagnosticsEngine::Level Level);
868be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void endDiagnostic(DiagOrStoredDiag D,
872a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                             DiagnosticsEngine::Level Level);
882a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek};
897800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekclass SDiagsWriter : public DiagnosticConsumer {
912a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  friend class SDiagsRenderer;
9214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
9314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  struct SharedState;
9414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
95cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  explicit SDiagsWriter(IntrusiveRefCntPtr<SharedState> State)
9614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    : LangOpts(0), OriginalInstance(false), State(State) { }
9714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
9814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregorpublic:
99cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SDiagsWriter(raw_ostream *os, DiagnosticOptions *diags)
10014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    : LangOpts(0), OriginalInstance(true), State(new SharedState(os, diags))
10114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  {
1027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    EmitPreamble();
10302ae32ae110eeb1ef785bf5ad9cdce1c001a5fa1Devang Patel  }
104db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
1057800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  ~SDiagsWriter() {}
1067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
1077800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1087800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                        const Diagnostic &Info);
1097800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
110153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  void BeginSourceFile(const LangOptions &LO,
111153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                       const Preprocessor *PP) {
112153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    LangOpts = &LO;
113153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  }
11429f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis
11529f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis  virtual void finish();
11629f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis
1177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekprivate:
1187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  /// \brief Emit the preamble for the serialized diagnostics.
1197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  void EmitPreamble();
1207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
1217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  /// \brief Emit the BLOCKINFO block.
1227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  void EmitBlockInfoBlock();
1230d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
1240b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  /// \brief Emit the META data block.
1250b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  void EmitMetaBlock();
126db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
127db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  /// \brief Start a DIAG block.
128db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  void EnterDiagBlock();
129db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
130db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  /// \brief End a DIAG block.
131db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  void ExitDiagBlock();
132db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
133db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  /// \brief Emit a DIAG record.
134db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  void EmitDiagnosticMessage(SourceLocation Loc,
135db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                             PresumedLoc PLoc,
136db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                             DiagnosticsEngine::Level Level,
137db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                             StringRef Message,
138db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                             const SourceManager *SM,
139db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                             DiagOrStoredDiag D);
140db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
141db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
142db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
143db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                       ArrayRef<FixItHint> Hints,
144db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                       const SourceManager &SM);
145db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
1462a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  /// \brief Emit a record for a CharSourceRange.
1472a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
1482a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek
1492a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  /// \brief Emit the string information for the category.
1502a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  unsigned getEmitCategory(unsigned category = 0);
1513baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
1523baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  /// \brief Emit the string information for diagnostic flags.
1533baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
1542a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                 unsigned DiagID = 0);
1550dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek
1560d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  /// \brief Emit (lazily) the file string and retrieved the file identifier.
1572a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  unsigned getEmitFile(const char *Filename);
1582a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
1592a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  /// \brief Add SourceLocation information the specified record.
16016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
1612a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                      PresumedLoc PLoc, RecordDataImpl &Record,
1622a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                      unsigned TokSize = 0);
1632a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
1640d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  /// \brief Add SourceLocation information the specified record.
165153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
16616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                      const SourceManager *SM,
1672a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                      unsigned TokSize = 0) {
16816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
16916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                   Record, TokSize);
1702a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  }
1710d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
17296dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  /// \brief Add CharSourceRange information the specified record.
17329f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis  void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
1742a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                  const SourceManager &SM);
17596dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek
1767800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  /// \brief The version of the diagnostics file.
1777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  enum { Version = 1 };
1787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
17914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// \brief Language options, which can differ from one clone of this client
18014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// to another.
181153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  const LangOptions *LangOpts;
1827800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
18314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// \brief Whether this is the original instance (rather than one of its
18414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// clones), responsible for writing the file at the end.
18514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  bool OriginalInstance;
1867800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
18714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// \brief State that is shared among the various clones of this diagnostic
18814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// consumer.
189cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  struct SharedState : RefCountedBase<SharedState> {
190cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SharedState(raw_ostream *os, DiagnosticOptions *diags)
19114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor      : DiagOpts(diags), Stream(Buffer), OS(os), EmittedAnyDiagBlocks(false) { }
1927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
19314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief Diagnostic options.
194cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
1957800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
19614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief The byte buffer for the serialized content.
19714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    SmallString<1024> Buffer;
19814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
19914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief The BitStreamWriter for the serialized diagnostics.
20014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    llvm::BitstreamWriter Stream;
20114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
20214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief The name of the diagnostics file.
203cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    OwningPtr<raw_ostream> OS;
20414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
20514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief The set of constructed record abbreviations.
20614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    AbbreviationMap Abbrevs;
20745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek
20814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief A utility buffer for constructing record content.
20914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    RecordData Record;
21014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
21114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief A text buffer for rendering diagnostic text.
21214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    SmallString<256> diagBuf;
21314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
21414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief The collection of diagnostic categories used.
21514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    llvm::DenseSet<unsigned> Categories;
21614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
21714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief The collection of files used.
21814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    llvm::DenseMap<const char *, unsigned> Files;
21945d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek
220cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> >
22114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    DiagFlagsTy;
222db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
22314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief Map for uniquing strings.
22414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    DiagFlagsTy DiagFlags;
22514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
22614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// \brief Whether we have already started emission of any DIAG blocks. Once
22714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// this becomes \c true, we never close a DIAG block until we know that we're
22814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    /// starting another one or we're done.
22914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    bool EmittedAnyDiagBlocks;
23014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  };
23114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
23214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  /// \brief State shared among the various clones of this diagnostic consumer.
233cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  IntrusiveRefCntPtr<SharedState> State;
2347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek};
2357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end anonymous namespace
2367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2377800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace clang {
2387800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace serialized_diags {
239cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri GribenkoDiagnosticConsumer *create(raw_ostream *OS, DiagnosticOptions *diags) {
2402a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  return new SDiagsWriter(OS, diags);
2417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
2427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end namespace serialized_diags
2437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end namespace clang
2447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===//
2467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// Serialization methods.
2477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===//
2487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2497800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits a block ID in the BLOCKINFO block.
2507800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void EmitBlockID(unsigned ID, const char *Name,
2517800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                        llvm::BitstreamWriter &Stream,
2527800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                        RecordDataImpl &Record) {
2537800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Record.clear();
2547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Record.push_back(ID);
2557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
2567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // Emit the block name if present.
2587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  if (Name == 0 || Name[0] == 0)
2597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    return;
2607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Record.clear();
2627800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2637800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  while (*Name)
2647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    Record.push_back(*Name++);
2657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
2677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
2687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits a record ID in the BLOCKINFO block.
2707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void EmitRecordID(unsigned ID, const char *Name,
2717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                         llvm::BitstreamWriter &Stream,
2727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                         RecordDataImpl &Record){
2737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Record.clear();
2747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Record.push_back(ID);
2757800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2767800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  while (*Name)
2777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek    Record.push_back(*Name++);
2787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2797800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
2807800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
2817800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
2820d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenekvoid SDiagsWriter::AddLocToRecord(SourceLocation Loc,
28316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                  const SourceManager *SM,
2842a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                  PresumedLoc PLoc,
285153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  RecordDataImpl &Record,
286153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek                                  unsigned TokSize) {
2872a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  if (PLoc.isInvalid()) {
2882a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek    // Emit a "sentinel" location.
289153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Record.push_back((unsigned)0); // File.
290153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Record.push_back((unsigned)0); // Line.
291153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Record.push_back((unsigned)0); // Column.
292153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    Record.push_back((unsigned)0); // Offset.
2932a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek    return;
2942a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  }
2952a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek
2962a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  Record.push_back(getEmitFile(PLoc.getFilename()));
2972a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  Record.push_back(PLoc.getLine());
2982a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  Record.push_back(PLoc.getColumn()+TokSize);
29916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  Record.push_back(SM->getFileOffset(Loc));
3002a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek}
3012a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek
30296dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenekvoid SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
30329f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis                                              RecordDataImpl &Record,
3042a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                              const SourceManager &SM) {
30516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  AddLocToRecord(Range.getBegin(), Record, &SM);
306153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  unsigned TokSize = 0;
307153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek  if (Range.isTokenRange())
308153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek    TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
30929f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis                                        SM, *LangOpts);
310153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek
31116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
31296dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek}
31396dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek
3142a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekunsigned SDiagsWriter::getEmitFile(const char *FileName){
3152a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  if (!FileName)
3160d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek    return 0;
3170d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
31814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  unsigned &entry = State->Files[FileName];
3190d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  if (entry)
3200d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek    return entry;
3210d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
3220d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  // Lazily generate the record for the file.
32314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  entry = State->Files.size();
3240d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  RecordData Record;
3250d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Record.push_back(RECORD_FILENAME);
3260d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Record.push_back(entry);
3272a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  Record.push_back(0); // For legacy.
3282a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  Record.push_back(0); // For legacy.
3292a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  StringRef Name(FileName);
3300d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Record.push_back(Name.size());
33114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record,
33214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor                                   Name);
3330d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
3340d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  return entry;
3350d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek}
3360d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
33729f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidisvoid SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
3382a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                       const SourceManager &SM) {
33914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Record.clear();
34014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Record.push_back(RECORD_SOURCE_RANGE);
34114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  AddCharSourceRangeToRecord(R, State->Record, SM);
34214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE),
34314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor                                     State->Record);
3442a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek}
3452a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek
3467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits the preamble of the diagnostics file.
3477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitPreamble() {
3487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // Emit the file header.
34914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.Emit((unsigned)'D', 8);
35014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.Emit((unsigned)'I', 8);
35114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.Emit((unsigned)'A', 8);
35214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.Emit((unsigned)'G', 8);
353069f9c29802f650a793877fa4c9a34853de9ed98Ted Kremenek
3547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  EmitBlockInfoBlock();
3550b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  EmitMetaBlock();
3567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
3577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
3582a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenekstatic void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
3592a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  using namespace llvm;
3600d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID.
3612a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line.
3622a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column.
3632a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset;
3642a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek}
36596dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek
36696dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenekstatic void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
36796dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  AddSourceLocationAbbrev(Abbrev);
36896dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  AddSourceLocationAbbrev(Abbrev);
36996dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek}
37096dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek
3717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitBlockInfoBlock() {
37214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.EnterBlockInfoBlock(3);
3730b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek
3740b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  using namespace llvm;
37514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  llvm::BitstreamWriter &Stream = State->Stream;
37614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  RecordData &Record = State->Record;
37714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  AbbreviationMap &Abbrevs = State->Abbrevs;
3780b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek
3790b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  // ==---------------------------------------------------------------------==//
3800b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  // The subsequent records and Abbrevs are for the "Meta" block.
3810b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  // ==---------------------------------------------------------------------==//
3820b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek
3830b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  EmitBlockID(BLOCK_META, "Meta", Stream, Record);
3840b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  EmitRecordID(RECORD_VERSION, "Version", Stream, Record);
3850b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
3860b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION));
3870b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
3880b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev));
3890b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek
3907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // ==---------------------------------------------------------------------==//
3917800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // The subsequent records and Abbrevs are for the "Diagnostic" block.
3927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // ==---------------------------------------------------------------------==//
3937800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
39445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek  EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record);
39545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek  EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record);
3962a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record);
3970dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record);
3983baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record);
3990d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record);
40096dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record);
4013baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
4027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // Emit abbreviation for RECORD_DIAG.
4030b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Abbrev = new BitCodeAbbrev();
4047800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
40545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3));  // Diag level.
4062a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  AddSourceLocationAbbrev(Abbrev);
40745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
40845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
4097800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
4107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
4117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
4122a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek
4130dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  // Emit abbrevation for RECORD_CATEGORY.
4140dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Abbrev = new BitCodeAbbrev();
4150dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
4160dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
4170dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));  // Text size.
4180dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // Category text.
4190dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
4200dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek
4212a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  // Emit abbrevation for RECORD_SOURCE_RANGE.
4222a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  Abbrev = new BitCodeAbbrev();
4232a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
42496dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  AddRangeLocationAbbrev(Abbrev);
4252a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek  Abbrevs.set(RECORD_SOURCE_RANGE,
4262a20b4fac5d06e2afc4980e7ef1b659c39c27c7bTed Kremenek              Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
4273baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
4283baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  // Emit the abbreviation for RECORD_DIAG_FLAG.
4293baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Abbrev = new BitCodeAbbrev();
4303baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
4313baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
4323baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
4333baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
4343baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
4353baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek                                                           Abbrev));
4360d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
4370d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  // Emit the abbreviation for RECORD_FILENAME.
4387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrev = new BitCodeAbbrev();
43928eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
4400d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
4410d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
4420d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time.
4437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
4447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
4450d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek  Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
4467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                                                          Abbrev));
44796dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek
44896dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  // Emit the abbreviation for RECORD_FIXIT.
44996dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  Abbrev = new BitCodeAbbrev();
45096dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
45196dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  AddRangeLocationAbbrev(Abbrev);
45296dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
45396dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // FixIt text.
45496dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
45596dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek                                                       Abbrev));
4567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
4577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  Stream.ExitBlock();
4587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
4597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
4600b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenekvoid SDiagsWriter::EmitMetaBlock() {
46114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  llvm::BitstreamWriter &Stream = State->Stream;
46214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  RecordData &Record = State->Record;
46314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  AbbreviationMap &Abbrevs = State->Abbrevs;
46414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
4650b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Stream.EnterSubblock(BLOCK_META, 3);
4660b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Record.clear();
4670b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Record.push_back(RECORD_VERSION);
4680b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Record.push_back(Version);
4690b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
4700b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek  Stream.ExitBlock();
4710b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek}
4720b69aa856308f6b35f8b96ef269a482558f2966bTed Kremenek
4732a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekunsigned SDiagsWriter::getEmitCategory(unsigned int category) {
47414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  if (State->Categories.count(category))
4753baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    return category;
4760dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek
47714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Categories.insert(category);
4780dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek
4790dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  // We use a local version of 'Record' so that we can be generating
4800dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  // another record when we lazily generate one for the category entry.
4810dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  RecordData Record;
4820dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Record.push_back(RECORD_CATEGORY);
4833baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  Record.push_back(category);
4843baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  StringRef catName = DiagnosticIDs::getCategoryNameFromID(category);
4850dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek  Record.push_back(catName.size());
48614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record,
48714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor                                   catName);
4883baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
4893baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  return category;
4903baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek}
4913baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
4923baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenekunsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
4932a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                             unsigned DiagID) {
4943baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  if (DiagLevel == DiagnosticsEngine::Note)
4953baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    return 0; // No flag for notes.
4963baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
4972a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
4983baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  if (FlagName.empty())
4993baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    return 0;
5003baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
5013baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  // Here we assume that FlagName points to static data whose pointer
5023baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  // value is fixed.  This allows us to unique by diagnostic groups.
5033baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  const void *data = FlagName.data();
50414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  std::pair<unsigned, StringRef> &entry = State->DiagFlags[data];
5053baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  if (entry.first == 0) {
50614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    entry.first = State->DiagFlags.size();
5073baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    entry.second = FlagName;
5083baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
5093baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    // Lazily emit the string in a separate record.
5103baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    RecordData Record;
5113baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    Record.push_back(RECORD_DIAG_FLAG);
5123baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    Record.push_back(entry.first);
5133baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek    Record.push_back(FlagName.size());
51414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG),
51514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor                                     Record, FlagName);
5163baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  }
5173baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek
5183baf63d37d0b6267885b584db1106232fc036cb9Ted Kremenek  return entry.first;
5190dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek}
5200dbadc4a8e54df02aab05d5fe45f2048a2e84c6dTed Kremenek
5217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
5227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek                                    const Diagnostic &Info) {
523db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // Enter the block for a non-note diagnostic immediately, rather than waiting
524db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // for beginDiagnostic, in case associated notes are emitted before we get
525db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // there.
52659b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek  if (DiagLevel != DiagnosticsEngine::Note) {
52714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    if (State->EmittedAnyDiagBlocks)
528db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith      ExitDiagBlock();
529db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
530db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    EnterDiagBlock();
53114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    State->EmittedAnyDiagBlocks = true;
53259b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek  }
5332a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
5342a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  // Compute the diagnostic text.
53514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->diagBuf.clear();
53614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  Info.FormatDiagnostic(State->diagBuf);
5372a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
538db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  if (Info.getLocation().isInvalid()) {
539db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    // Special-case diagnostics with no location. We may not have entered a
540db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    // source file in this case, so we can't use the normal DiagnosticsRenderer
541db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    // machinery.
54263631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek
54363631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek    // Make sure we bracket all notes as "sub-diagnostics".  This matches
54463631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek    // the behavior in SDiagsRenderer::emitDiagnostic().
54563631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek    if (DiagLevel == DiagnosticsEngine::Note)
54663631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek      EnterDiagBlock();
54763631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek
548db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
54914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor                          State->diagBuf, 0, &Info);
55063631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek
55163631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek    if (DiagLevel == DiagnosticsEngine::Note)
55263631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek      ExitDiagBlock();
55363631bd173df1decfff98ae6a7ed7f3d5f886b86Ted Kremenek
554db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    return;
555db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  }
556db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
557db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  assert(Info.hasSourceManager() && LangOpts &&
558db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith         "Unexpected diagnostic with valid location outside of a source file");
55914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
5602a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek  Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
56114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor                          State->diagBuf.str(),
5622a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                          Info.getRanges(),
5632a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                          llvm::makeArrayRef(Info.getFixItHints(),
5642a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                             Info.getNumFixItHints()),
565db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                          &Info.getSourceManager(),
5662a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                          &Info);
5672a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek}
5682a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
569db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
570db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                         PresumedLoc PLoc,
571db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                         DiagnosticsEngine::Level Level,
572db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                         StringRef Message,
573db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                         const SourceManager *SM,
574db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                         DiagOrStoredDiag D) {
57514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  llvm::BitstreamWriter &Stream = State->Stream;
57614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  RecordData &Record = State->Record;
57714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  AbbreviationMap &Abbrevs = State->Abbrevs;
57814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
579db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // Emit the RECORD_DIAG record.
580db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Record.clear();
581db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Record.push_back(RECORD_DIAG);
582db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Record.push_back(Level);
583db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  AddLocToRecord(Loc, SM, PLoc, Record);
584db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
585db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
586db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    // Emit the category string lazily and get the category ID.
587db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
588db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.push_back(getEmitCategory(DiagID));
589db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    // Emit the diagnostic flag string lazily and get the mapped ID.
590db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.push_back(getEmitDiagnosticFlag(Level, Info->getID()));
591db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  } else {
592db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.push_back(getEmitCategory());
593db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.push_back(getEmitDiagnosticFlag(Level));
594db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  }
595db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
596db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Record.push_back(Message.size());
597db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
598db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith}
599db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
6002a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekvoid
6012a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed KremenekSDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
6022a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                      PresumedLoc PLoc,
6032a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                      DiagnosticsEngine::Level Level,
6042a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                      StringRef Message,
6052a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                      ArrayRef<clang::CharSourceRange> Ranges,
60616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                      const SourceManager *SM,
6078be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                      DiagOrStoredDiag D) {
608db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
609db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith}
6102a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
611db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::EnterDiagBlock() {
61214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.EnterSubblock(BLOCK_DIAG, 4);
613db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith}
6142a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
615db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::ExitDiagBlock() {
61614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->Stream.ExitBlock();
6172a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek}
6182a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
6198be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
6202a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                     DiagnosticsEngine::Level Level) {
621db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  if (Level == DiagnosticsEngine::Note)
622db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Writer.EnterDiagBlock();
6232a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek}
6242a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
6258be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
6262a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek                                   DiagnosticsEngine::Level Level) {
627db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // Only end note diagnostics here, because we can't be sure when we've seen
628db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // the last note associated with a non-note diagnostic.
629db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  if (Level == DiagnosticsEngine::Note)
630db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Writer.ExitDiagBlock();
6312a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek}
63296dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek
633db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
634db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                   ArrayRef<FixItHint> Hints,
635db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                   const SourceManager &SM) {
63614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  llvm::BitstreamWriter &Stream = State->Stream;
63714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  RecordData &Record = State->Record;
63814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  AbbreviationMap &Abbrevs = State->Abbrevs;
63914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
64096dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  // Emit Source Ranges.
641db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
642db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith       I != E; ++I)
643db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    if (I->isValid())
644db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith      EmitCharSourceRange(*I, SM);
645db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
64696dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek  // Emit FixIts.
647db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
648db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith       I != E; ++I) {
649db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    const FixItHint &Fix = *I;
650db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    if (Fix.isNull())
65196dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek      continue;
652db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.clear();
653db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.push_back(RECORD_FIXIT);
654db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM);
655db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Record.push_back(Fix.CodeToInsert.size());
656db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
657db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                              Fix.CodeToInsert);
65859b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek  }
6597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
6607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek
661db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsRenderer::emitCodeContext(SourceLocation Loc,
662db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                     DiagnosticsEngine::Level Level,
663db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                     SmallVectorImpl<CharSourceRange> &Ranges,
664db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                     ArrayRef<FixItHint> Hints,
665db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                                     const SourceManager &SM) {
666db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Writer.EmitCodeContext(Ranges, Hints, SM);
667db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith}
668db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
66916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
67016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                              const SourceManager *SM) {
671db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Writer.EnterDiagBlock();
672db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
673db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
674db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith                               Message, SM, DiagOrStoredDiag());
675db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  Writer.ExitDiagBlock();
6762a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek}
6772a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek
67829f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidisvoid SDiagsWriter::finish() {
67914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  // The original instance is responsible for writing the file.
68014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  if (!OriginalInstance)
68114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor    return;
68214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor
683db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith  // Finish off any diagnostic we were in the process of emitting.
68414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  if (State->EmittedAnyDiagBlocks)
685db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith    ExitDiagBlock();
6860d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek
6877800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek  // Write the generated bitstream to "Out".
68814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->OS->write((char *)&State->Buffer.front(), State->Buffer.size());
68914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->OS->flush();
690db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith
69114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor  State->OS.reset(0);
6927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}
693