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: 62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitDiagnosticMessage(SourceLocation Loc, 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PresumedLoc PLoc, 64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine::Level Level, 65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Message, 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<CharSourceRange> Ranges, 67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager *SM, 68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagOrStoredDiag D) override; 69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine::Level Level, 72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<CharSourceRange> Ranges, 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager &SM) override {} 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitNote(SourceLocation Loc, StringRef Message, 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager *SM) override; 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitCodeContext(SourceLocation Loc, 79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine::Level Level, 80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallVectorImpl<CharSourceRange>& Ranges, 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<FixItHint> Hints, 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager &SM) override; 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void beginDiagnostic(DiagOrStoredDiag D, 85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine::Level Level) override; 86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void endDiagnostic(DiagOrStoredDiag D, 87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine::Level Level) override; 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) 966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : LangOpts(nullptr), OriginalInstance(false), State(State) {} 9714afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor 9814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregorpublic: 99cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SDiagsWriter(raw_ostream *os, DiagnosticOptions *diags) 1006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : LangOpts(nullptr), OriginalInstance(true), 1016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines State(new SharedState(os, diags)) 10214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor { 1037800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitPreamble(); 10402ae32ae110eeb1ef785bf5ad9cdce1c001a5fa1Devang Patel } 105db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 1067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ~SDiagsWriter() {} 107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1087800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Diagnostic &Info) override; 110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override { 112153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek LangOpts = &LO; 113153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 11429f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidis 115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void finish() override; 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. 177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines enum { Version = 2 }; 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. 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<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. 2586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Name || 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, 5496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines State->diagBuf, nullptr, &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(), 5636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Info.getFixItHints(), 564db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith &Info.getSourceManager(), 5652a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek &Info); 5662a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek} 5672a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek 568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) { 569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines switch (Level) { 570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X; 571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Ignored) 572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Note) 573651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Remark) 574651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Warning) 575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Error) 576651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Fatal) 577651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#undef CASE 578651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 579651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 580651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm_unreachable("invalid diagnostic level"); 581651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 582651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 583db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc, 584db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith PresumedLoc PLoc, 585db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith DiagnosticsEngine::Level Level, 586db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith StringRef Message, 587db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith const SourceManager *SM, 588db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith DiagOrStoredDiag D) { 58914afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor llvm::BitstreamWriter &Stream = State->Stream; 59014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor RecordData &Record = State->Record; 59114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor AbbreviationMap &Abbrevs = State->Abbrevs; 59214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor 593db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith // Emit the RECORD_DIAG record. 594db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.clear(); 595db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(RECORD_DIAG); 596651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Record.push_back(getStableLevel(Level)); 597db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith AddLocToRecord(Loc, SM, PLoc, Record); 598db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 599db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) { 600db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith // Emit the category string lazily and get the category ID. 601db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); 602db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(getEmitCategory(DiagID)); 603db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith // Emit the diagnostic flag string lazily and get the mapped ID. 604db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(getEmitDiagnosticFlag(Level, Info->getID())); 605db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith } else { 606db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(getEmitCategory()); 607db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(getEmitDiagnosticFlag(Level)); 608db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith } 609db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 610db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(Message.size()); 611db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message); 612db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith} 613db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 6142a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenekvoid 6152a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed KremenekSDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, 6162a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek PresumedLoc PLoc, 6172a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek DiagnosticsEngine::Level Level, 6182a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek StringRef Message, 6192a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek ArrayRef<clang::CharSourceRange> Ranges, 62016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM, 6218be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek DiagOrStoredDiag D) { 622db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D); 623db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith} 6242a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek 625db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::EnterDiagBlock() { 62614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor State->Stream.EnterSubblock(BLOCK_DIAG, 4); 627db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith} 6282a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek 629db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::ExitDiagBlock() { 63014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor State->Stream.ExitBlock(); 6312a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek} 6322a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek 6338be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D, 6342a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek DiagnosticsEngine::Level Level) { 635db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith if (Level == DiagnosticsEngine::Note) 636db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.EnterDiagBlock(); 6372a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek} 6382a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek 6398be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekvoid SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D, 6402a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek DiagnosticsEngine::Level Level) { 641db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith // Only end note diagnostics here, because we can't be sure when we've seen 642db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith // the last note associated with a non-note diagnostic. 643db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith if (Level == DiagnosticsEngine::Note) 644db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.ExitDiagBlock(); 6452a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek} 64696dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek 647db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, 648db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith ArrayRef<FixItHint> Hints, 649db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith const SourceManager &SM) { 65014afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor llvm::BitstreamWriter &Stream = State->Stream; 65114afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor RecordData &Record = State->Record; 65214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor AbbreviationMap &Abbrevs = State->Abbrevs; 65314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor 65496dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek // Emit Source Ranges. 655db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); 656db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith I != E; ++I) 657db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith if (I->isValid()) 658db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith EmitCharSourceRange(*I, SM); 659db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 66096dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek // Emit FixIts. 661db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 662db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith I != E; ++I) { 663db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith const FixItHint &Fix = *I; 664db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith if (Fix.isNull()) 66596dcadec26244e028d59287ea1b249802c8fc2bcTed Kremenek continue; 666db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.clear(); 667db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(RECORD_FIXIT); 668db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM); 669db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Record.push_back(Fix.CodeToInsert.size()); 670db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record, 671db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Fix.CodeToInsert); 67259b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek } 6737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 6747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 675db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smithvoid SDiagsRenderer::emitCodeContext(SourceLocation Loc, 676db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith DiagnosticsEngine::Level Level, 677db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith SmallVectorImpl<CharSourceRange> &Ranges, 678db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith ArrayRef<FixItHint> Hints, 679db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith const SourceManager &SM) { 680db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.EmitCodeContext(Ranges, Hints, SM); 681db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith} 682db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 68316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message, 68416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM) { 685db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.EnterDiagBlock(); 686db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc(); 687db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, 688db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Message, SM, DiagOrStoredDiag()); 689db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith Writer.ExitDiagBlock(); 6902a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek} 6912a76410c0a23a6feb98d0f13e9c8bfa0638d3adfTed Kremenek 69229f2787b6da552018a7716f18f5bd8f67bd6edb5Argyrios Kyrtzidisvoid SDiagsWriter::finish() { 69314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor // The original instance is responsible for writing the file. 69414afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor if (!OriginalInstance) 69514afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor return; 69614afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor 697db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith // Finish off any diagnostic we were in the process of emitting. 69814afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor if (State->EmittedAnyDiagBlocks) 699db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith ExitDiagBlock(); 7000d34e6ebd9d8b6e97106e12c13c6057f9829b946Ted Kremenek 7017800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Write the generated bitstream to "Out". 70214afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor State->OS->write((char *)&State->Buffer.front(), State->Buffer.size()); 70314afab36c73c32a831838ba80f36136a80d9e6dbDouglas Gregor State->OS->flush(); 704db309ae1bfa7c30ed3b2b9e59a316b8fef2e56b6Richard Smith 7056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines State->OS.reset(nullptr); 7067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 707