clang API Documentation
00001 //===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include <vector> 00011 #include "llvm/Support/raw_ostream.h" 00012 #include "llvm/ADT/StringRef.h" 00013 #include "llvm/ADT/SmallString.h" 00014 #include "llvm/ADT/DenseSet.h" 00015 #include "clang/Basic/SourceManager.h" 00016 #include "clang/Basic/FileManager.h" 00017 #include "clang/Basic/Diagnostic.h" 00018 #include "clang/Basic/Version.h" 00019 #include "clang/Lex/Lexer.h" 00020 #include "clang/Frontend/SerializedDiagnosticPrinter.h" 00021 #include "clang/Frontend/DiagnosticRenderer.h" 00022 00023 using namespace clang; 00024 using namespace clang::serialized_diags; 00025 00026 namespace { 00027 00028 class AbbreviationMap { 00029 llvm::DenseMap<unsigned, unsigned> Abbrevs; 00030 public: 00031 AbbreviationMap() {} 00032 00033 void set(unsigned recordID, unsigned abbrevID) { 00034 assert(Abbrevs.find(recordID) == Abbrevs.end() 00035 && "Abbreviation already set."); 00036 Abbrevs[recordID] = abbrevID; 00037 } 00038 00039 unsigned get(unsigned recordID) { 00040 assert(Abbrevs.find(recordID) != Abbrevs.end() && 00041 "Abbreviation not set."); 00042 return Abbrevs[recordID]; 00043 } 00044 }; 00045 00046 typedef llvm::SmallVector<uint64_t, 64> RecordData; 00047 typedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl; 00048 00049 class SDiagsWriter; 00050 00051 class SDiagsRenderer : public DiagnosticNoteRenderer { 00052 SDiagsWriter &Writer; 00053 RecordData &Record; 00054 public: 00055 SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record, 00056 const LangOptions &LangOpts, 00057 const DiagnosticOptions &DiagOpts) 00058 : DiagnosticNoteRenderer(LangOpts, DiagOpts), 00059 Writer(Writer), Record(Record){} 00060 00061 virtual ~SDiagsRenderer() {} 00062 00063 protected: 00064 virtual void emitDiagnosticMessage(SourceLocation Loc, 00065 PresumedLoc PLoc, 00066 DiagnosticsEngine::Level Level, 00067 StringRef Message, 00068 ArrayRef<CharSourceRange> Ranges, 00069 const SourceManager *SM, 00070 DiagOrStoredDiag D); 00071 00072 virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 00073 DiagnosticsEngine::Level Level, 00074 ArrayRef<CharSourceRange> Ranges, 00075 const SourceManager &SM) {} 00076 00077 void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM); 00078 00079 virtual void emitCodeContext(SourceLocation Loc, 00080 DiagnosticsEngine::Level Level, 00081 SmallVectorImpl<CharSourceRange>& Ranges, 00082 ArrayRef<FixItHint> Hints, 00083 const SourceManager &SM); 00084 00085 virtual void beginDiagnostic(DiagOrStoredDiag D, 00086 DiagnosticsEngine::Level Level); 00087 virtual void endDiagnostic(DiagOrStoredDiag D, 00088 DiagnosticsEngine::Level Level); 00089 }; 00090 00091 class SDiagsWriter : public DiagnosticConsumer { 00092 friend class SDiagsRenderer; 00093 public: 00094 explicit SDiagsWriter(llvm::raw_ostream *os, const DiagnosticOptions &diags) 00095 : LangOpts(0), DiagOpts(diags), 00096 Stream(Buffer), OS(os), inNonNoteDiagnostic(false) 00097 { 00098 EmitPreamble(); 00099 } 00100 00101 ~SDiagsWriter() {} 00102 00103 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 00104 const Diagnostic &Info); 00105 00106 void BeginSourceFile(const LangOptions &LO, 00107 const Preprocessor *PP) { 00108 LangOpts = &LO; 00109 } 00110 00111 virtual void finish(); 00112 00113 DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { 00114 // It makes no sense to clone this. 00115 return 0; 00116 } 00117 00118 private: 00119 /// \brief Emit the preamble for the serialized diagnostics. 00120 void EmitPreamble(); 00121 00122 /// \brief Emit the BLOCKINFO block. 00123 void EmitBlockInfoBlock(); 00124 00125 /// \brief Emit the META data block. 00126 void EmitMetaBlock(); 00127 00128 /// \brief Emit a record for a CharSourceRange. 00129 void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM); 00130 00131 /// \brief Emit the string information for the category. 00132 unsigned getEmitCategory(unsigned category = 0); 00133 00134 /// \brief Emit the string information for diagnostic flags. 00135 unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 00136 unsigned DiagID = 0); 00137 00138 /// \brief Emit (lazily) the file string and retrieved the file identifier. 00139 unsigned getEmitFile(const char *Filename); 00140 00141 /// \brief Add SourceLocation information the specified record. 00142 void AddLocToRecord(SourceLocation Loc, const SourceManager *SM, 00143 PresumedLoc PLoc, RecordDataImpl &Record, 00144 unsigned TokSize = 0); 00145 00146 /// \brief Add SourceLocation information the specified record. 00147 void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, 00148 const SourceManager *SM, 00149 unsigned TokSize = 0) { 00150 AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(), 00151 Record, TokSize); 00152 } 00153 00154 /// \brief Add CharSourceRange information the specified record. 00155 void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record, 00156 const SourceManager &SM); 00157 00158 /// \brief The version of the diagnostics file. 00159 enum { Version = 1 }; 00160 00161 const LangOptions *LangOpts; 00162 const DiagnosticOptions &DiagOpts; 00163 00164 /// \brief The byte buffer for the serialized content. 00165 SmallString<1024> Buffer; 00166 00167 /// \brief The BitStreamWriter for the serialized diagnostics. 00168 llvm::BitstreamWriter Stream; 00169 00170 /// \brief The name of the diagnostics file. 00171 OwningPtr<llvm::raw_ostream> OS; 00172 00173 /// \brief The set of constructed record abbreviations. 00174 AbbreviationMap Abbrevs; 00175 00176 /// \brief A utility buffer for constructing record content. 00177 RecordData Record; 00178 00179 /// \brief A text buffer for rendering diagnostic text. 00180 SmallString<256> diagBuf; 00181 00182 /// \brief The collection of diagnostic categories used. 00183 llvm::DenseSet<unsigned> Categories; 00184 00185 /// \brief The collection of files used. 00186 llvm::DenseMap<const char *, unsigned> Files; 00187 00188 typedef llvm::DenseMap<const void *, std::pair<unsigned, llvm::StringRef> > 00189 DiagFlagsTy; 00190 00191 /// \brief Map for uniquing strings. 00192 DiagFlagsTy DiagFlags; 00193 00194 /// \brief Flag indicating whether or not we are in the process of 00195 /// emitting a non-note diagnostic. 00196 bool inNonNoteDiagnostic; 00197 }; 00198 } // end anonymous namespace 00199 00200 namespace clang { 00201 namespace serialized_diags { 00202 DiagnosticConsumer *create(llvm::raw_ostream *OS, 00203 const DiagnosticOptions &diags) { 00204 return new SDiagsWriter(OS, diags); 00205 } 00206 } // end namespace serialized_diags 00207 } // end namespace clang 00208 00209 //===----------------------------------------------------------------------===// 00210 // Serialization methods. 00211 //===----------------------------------------------------------------------===// 00212 00213 /// \brief Emits a block ID in the BLOCKINFO block. 00214 static void EmitBlockID(unsigned ID, const char *Name, 00215 llvm::BitstreamWriter &Stream, 00216 RecordDataImpl &Record) { 00217 Record.clear(); 00218 Record.push_back(ID); 00219 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 00220 00221 // Emit the block name if present. 00222 if (Name == 0 || Name[0] == 0) 00223 return; 00224 00225 Record.clear(); 00226 00227 while (*Name) 00228 Record.push_back(*Name++); 00229 00230 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 00231 } 00232 00233 /// \brief Emits a record ID in the BLOCKINFO block. 00234 static void EmitRecordID(unsigned ID, const char *Name, 00235 llvm::BitstreamWriter &Stream, 00236 RecordDataImpl &Record){ 00237 Record.clear(); 00238 Record.push_back(ID); 00239 00240 while (*Name) 00241 Record.push_back(*Name++); 00242 00243 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 00244 } 00245 00246 void SDiagsWriter::AddLocToRecord(SourceLocation Loc, 00247 const SourceManager *SM, 00248 PresumedLoc PLoc, 00249 RecordDataImpl &Record, 00250 unsigned TokSize) { 00251 if (PLoc.isInvalid()) { 00252 // Emit a "sentinel" location. 00253 Record.push_back((unsigned)0); // File. 00254 Record.push_back((unsigned)0); // Line. 00255 Record.push_back((unsigned)0); // Column. 00256 Record.push_back((unsigned)0); // Offset. 00257 return; 00258 } 00259 00260 Record.push_back(getEmitFile(PLoc.getFilename())); 00261 Record.push_back(PLoc.getLine()); 00262 Record.push_back(PLoc.getColumn()+TokSize); 00263 Record.push_back(SM->getFileOffset(Loc)); 00264 } 00265 00266 void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, 00267 RecordDataImpl &Record, 00268 const SourceManager &SM) { 00269 AddLocToRecord(Range.getBegin(), Record, &SM); 00270 unsigned TokSize = 0; 00271 if (Range.isTokenRange()) 00272 TokSize = Lexer::MeasureTokenLength(Range.getEnd(), 00273 SM, *LangOpts); 00274 00275 AddLocToRecord(Range.getEnd(), Record, &SM, TokSize); 00276 } 00277 00278 unsigned SDiagsWriter::getEmitFile(const char *FileName){ 00279 if (!FileName) 00280 return 0; 00281 00282 unsigned &entry = Files[FileName]; 00283 if (entry) 00284 return entry; 00285 00286 // Lazily generate the record for the file. 00287 entry = Files.size(); 00288 RecordData Record; 00289 Record.push_back(RECORD_FILENAME); 00290 Record.push_back(entry); 00291 Record.push_back(0); // For legacy. 00292 Record.push_back(0); // For legacy. 00293 StringRef Name(FileName); 00294 Record.push_back(Name.size()); 00295 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FILENAME), Record, Name); 00296 00297 return entry; 00298 } 00299 00300 void SDiagsWriter::EmitCharSourceRange(CharSourceRange R, 00301 const SourceManager &SM) { 00302 Record.clear(); 00303 Record.push_back(RECORD_SOURCE_RANGE); 00304 AddCharSourceRangeToRecord(R, Record, SM); 00305 Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_SOURCE_RANGE), Record); 00306 } 00307 00308 /// \brief Emits the preamble of the diagnostics file. 00309 void SDiagsWriter::EmitPreamble() { 00310 // Emit the file header. 00311 Stream.Emit((unsigned)'D', 8); 00312 Stream.Emit((unsigned)'I', 8); 00313 Stream.Emit((unsigned)'A', 8); 00314 Stream.Emit((unsigned)'G', 8); 00315 00316 EmitBlockInfoBlock(); 00317 EmitMetaBlock(); 00318 } 00319 00320 static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) { 00321 using namespace llvm; 00322 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID. 00323 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line. 00324 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column. 00325 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset; 00326 } 00327 00328 static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) { 00329 AddSourceLocationAbbrev(Abbrev); 00330 AddSourceLocationAbbrev(Abbrev); 00331 } 00332 00333 void SDiagsWriter::EmitBlockInfoBlock() { 00334 Stream.EnterBlockInfoBlock(3); 00335 00336 using namespace llvm; 00337 00338 // ==---------------------------------------------------------------------==// 00339 // The subsequent records and Abbrevs are for the "Meta" block. 00340 // ==---------------------------------------------------------------------==// 00341 00342 EmitBlockID(BLOCK_META, "Meta", Stream, Record); 00343 EmitRecordID(RECORD_VERSION, "Version", Stream, Record); 00344 BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 00345 Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION)); 00346 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 00347 Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev)); 00348 00349 // ==---------------------------------------------------------------------==// 00350 // The subsequent records and Abbrevs are for the "Diagnostic" block. 00351 // ==---------------------------------------------------------------------==// 00352 00353 EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record); 00354 EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record); 00355 EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record); 00356 EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record); 00357 EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record); 00358 EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record); 00359 EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record); 00360 00361 // Emit abbreviation for RECORD_DIAG. 00362 Abbrev = new BitCodeAbbrev(); 00363 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG)); 00364 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level. 00365 AddSourceLocationAbbrev(Abbrev); 00366 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category. 00367 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 00368 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 00369 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. 00370 Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 00371 00372 // Emit abbrevation for RECORD_CATEGORY. 00373 Abbrev = new BitCodeAbbrev(); 00374 Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY)); 00375 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID. 00376 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size. 00377 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text. 00378 Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 00379 00380 // Emit abbrevation for RECORD_SOURCE_RANGE. 00381 Abbrev = new BitCodeAbbrev(); 00382 Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE)); 00383 AddRangeLocationAbbrev(Abbrev); 00384 Abbrevs.set(RECORD_SOURCE_RANGE, 00385 Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 00386 00387 // Emit the abbreviation for RECORD_DIAG_FLAG. 00388 Abbrev = new BitCodeAbbrev(); 00389 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG)); 00390 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 00391 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 00392 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text. 00393 Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 00394 Abbrev)); 00395 00396 // Emit the abbreviation for RECORD_FILENAME. 00397 Abbrev = new BitCodeAbbrev(); 00398 Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME)); 00399 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID. 00400 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size. 00401 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time. 00402 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 00403 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text. 00404 Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 00405 Abbrev)); 00406 00407 // Emit the abbreviation for RECORD_FIXIT. 00408 Abbrev = new BitCodeAbbrev(); 00409 Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT)); 00410 AddRangeLocationAbbrev(Abbrev); 00411 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 00412 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text. 00413 Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 00414 Abbrev)); 00415 00416 Stream.ExitBlock(); 00417 } 00418 00419 void SDiagsWriter::EmitMetaBlock() { 00420 Stream.EnterSubblock(BLOCK_META, 3); 00421 Record.clear(); 00422 Record.push_back(RECORD_VERSION); 00423 Record.push_back(Version); 00424 Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record); 00425 Stream.ExitBlock(); 00426 } 00427 00428 unsigned SDiagsWriter::getEmitCategory(unsigned int category) { 00429 if (Categories.count(category)) 00430 return category; 00431 00432 Categories.insert(category); 00433 00434 // We use a local version of 'Record' so that we can be generating 00435 // another record when we lazily generate one for the category entry. 00436 RecordData Record; 00437 Record.push_back(RECORD_CATEGORY); 00438 Record.push_back(category); 00439 StringRef catName = DiagnosticIDs::getCategoryNameFromID(category); 00440 Record.push_back(catName.size()); 00441 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_CATEGORY), Record, catName); 00442 00443 return category; 00444 } 00445 00446 unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 00447 unsigned DiagID) { 00448 if (DiagLevel == DiagnosticsEngine::Note) 00449 return 0; // No flag for notes. 00450 00451 StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID); 00452 if (FlagName.empty()) 00453 return 0; 00454 00455 // Here we assume that FlagName points to static data whose pointer 00456 // value is fixed. This allows us to unique by diagnostic groups. 00457 const void *data = FlagName.data(); 00458 std::pair<unsigned, StringRef> &entry = DiagFlags[data]; 00459 if (entry.first == 0) { 00460 entry.first = DiagFlags.size(); 00461 entry.second = FlagName; 00462 00463 // Lazily emit the string in a separate record. 00464 RecordData Record; 00465 Record.push_back(RECORD_DIAG_FLAG); 00466 Record.push_back(entry.first); 00467 Record.push_back(FlagName.size()); 00468 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG_FLAG), 00469 Record, FlagName); 00470 } 00471 00472 return entry.first; 00473 } 00474 00475 void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 00476 const Diagnostic &Info) { 00477 if (DiagLevel != DiagnosticsEngine::Note) { 00478 if (inNonNoteDiagnostic) { 00479 // We have encountered a non-note diagnostic. Finish up the previous 00480 // diagnostic block before starting a new one. 00481 Stream.ExitBlock(); 00482 } 00483 inNonNoteDiagnostic = true; 00484 } 00485 00486 // Compute the diagnostic text. 00487 diagBuf.clear(); 00488 Info.FormatDiagnostic(diagBuf); 00489 00490 const SourceManager * 00491 SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0; 00492 SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts); 00493 Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, 00494 diagBuf.str(), 00495 Info.getRanges(), 00496 llvm::makeArrayRef(Info.getFixItHints(), 00497 Info.getNumFixItHints()), 00498 SM, 00499 &Info); 00500 } 00501 00502 void 00503 SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, 00504 PresumedLoc PLoc, 00505 DiagnosticsEngine::Level Level, 00506 StringRef Message, 00507 ArrayRef<clang::CharSourceRange> Ranges, 00508 const SourceManager *SM, 00509 DiagOrStoredDiag D) { 00510 // Emit the RECORD_DIAG record. 00511 Writer.Record.clear(); 00512 Writer.Record.push_back(RECORD_DIAG); 00513 Writer.Record.push_back(Level); 00514 Writer.AddLocToRecord(Loc, SM, PLoc, Record); 00515 00516 if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) { 00517 // Emit the category string lazily and get the category ID. 00518 unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); 00519 Writer.Record.push_back(Writer.getEmitCategory(DiagID)); 00520 // Emit the diagnostic flag string lazily and get the mapped ID. 00521 Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level, Info->getID())); 00522 } 00523 else { 00524 Writer.Record.push_back(Writer.getEmitCategory()); 00525 Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level)); 00526 } 00527 00528 Writer.Record.push_back(Message.size()); 00529 Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG), 00530 Writer.Record, Message); 00531 } 00532 00533 void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D, 00534 DiagnosticsEngine::Level Level) { 00535 Writer.Stream.EnterSubblock(BLOCK_DIAG, 4); 00536 } 00537 00538 void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D, 00539 DiagnosticsEngine::Level Level) { 00540 if (D && Level != DiagnosticsEngine::Note) 00541 return; 00542 Writer.Stream.ExitBlock(); 00543 } 00544 00545 void SDiagsRenderer::emitCodeContext(SourceLocation Loc, 00546 DiagnosticsEngine::Level Level, 00547 SmallVectorImpl<CharSourceRange> &Ranges, 00548 ArrayRef<FixItHint> Hints, 00549 const SourceManager &SM) { 00550 // Emit Source Ranges. 00551 for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end(); 00552 it != ei; ++it) { 00553 if (it->isValid()) 00554 Writer.EmitCharSourceRange(*it, SM); 00555 } 00556 00557 // Emit FixIts. 00558 for (ArrayRef<FixItHint>::iterator it = Hints.begin(), et = Hints.end(); 00559 it != et; ++it) { 00560 const FixItHint &fix = *it; 00561 if (fix.isNull()) 00562 continue; 00563 Writer.Record.clear(); 00564 Writer.Record.push_back(RECORD_FIXIT); 00565 Writer.AddCharSourceRangeToRecord(fix.RemoveRange, Record, SM); 00566 Writer.Record.push_back(fix.CodeToInsert.size()); 00567 Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_FIXIT), Record, 00568 fix.CodeToInsert); 00569 } 00570 } 00571 00572 void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message, 00573 const SourceManager *SM) { 00574 Writer.Stream.EnterSubblock(BLOCK_DIAG, 4); 00575 RecordData Record; 00576 Record.push_back(RECORD_DIAG); 00577 Record.push_back(DiagnosticsEngine::Note); 00578 Writer.AddLocToRecord(Loc, Record, SM); 00579 Record.push_back(Writer.getEmitCategory()); 00580 Record.push_back(Writer.getEmitDiagnosticFlag(DiagnosticsEngine::Note)); 00581 Record.push_back(Message.size()); 00582 Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG), 00583 Record, Message); 00584 Writer.Stream.ExitBlock(); 00585 } 00586 00587 void SDiagsWriter::finish() { 00588 if (inNonNoteDiagnostic) { 00589 // Finish off any diagnostics we were in the process of emitting. 00590 Stream.ExitBlock(); 00591 inNonNoteDiagnostic = false; 00592 } 00593 00594 // Write the generated bitstream to "Out". 00595 OS->write((char *)&Buffer.front(), Buffer.size()); 00596 OS->flush(); 00597 00598 OS.reset(0); 00599 } 00600