void SerializedDiagnosticConsumer:: emitDiagnosticMessage(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, StringRef Text, const DiagnosticInfo &Info) { // Emit the diagnostic to bitcode. llvm::BitstreamWriter &Stream = State->Stream; RecordData &Record = State->Record; AbbreviationMap &Abbrevs = State->Abbrevs; StringRef filename = ""; if (Loc.isValid()) filename = SM.getIdentifierForBuffer(SM.findBufferContainingLoc(Loc)); // Emit the RECORD_DIAG record. Record.clear(); Record.push_back(RECORD_DIAG); Record.push_back(getDiagnosticLevel(Kind)); addLocToRecord(Loc, SM, filename, Record); // FIXME: Swift diagnostics currently have no category. Record.push_back(0); // FIXME: Swift diagnostics currently have no flags. Record.push_back(0); // Emit the message. Record.push_back(Text.size()); Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Text); // If the location is invalid, do not emit source ranges or fixits. if (Loc.isInvalid()) return; // Emit source ranges. auto RangeAbbrev = State->Abbrevs.get(RECORD_SOURCE_RANGE); for (const auto &R : Info.Ranges) { if (R.isInvalid()) continue; State->Record.clear(); State->Record.push_back(RECORD_SOURCE_RANGE); addRangeToRecord(R, SM, filename, State->Record); State->Stream.EmitRecordWithAbbrev(RangeAbbrev, State->Record); } // Emit FixIts. auto FixItAbbrev = State->Abbrevs.get(RECORD_FIXIT); for (const auto &F : Info.FixIts) { if (F.getRange().isValid()) { State->Record.clear(); State->Record.push_back(RECORD_FIXIT); addRangeToRecord(F.getRange(), SM, filename, State->Record); State->Record.push_back(F.getText().size()); Stream.EmitRecordWithBlob(FixItAbbrev, Record, F.getText()); } } }
/// \brief Extract a character immediately before \p Loc. If \p Loc is the /// start of the buffer, return '\f'. static char extractCharBefore(SourceManager &SM, SourceLoc Loc) { // We have to be careful not to go off the front of the buffer. auto bufferID = SM.findBufferContainingLoc(Loc); auto bufferRange = SM.getRangeForBuffer(bufferID); if (bufferRange.getStart() == Loc) return '\f'; auto chars = SM.extractText({Loc.getAdvancedLoc(-1), 1}, bufferID); assert(!chars.empty() && "Couldn't extractText with valid range"); return chars[0]; }
void SourceLoc::print(raw_ostream &OS, const SourceManager &SM, unsigned &LastBufferID) const { if (isInvalid()) { OS << "<invalid loc>"; return; } unsigned BufferID = SM.findBufferContainingLoc(*this); if (BufferID != LastBufferID) { OS << SM.getIdentifierForBuffer(BufferID); LastBufferID = BufferID; } else { OS << "line"; } auto LineAndCol = SM.getLineAndColumn(*this, BufferID); OS << ':' << LineAndCol.first << ':' << LineAndCol.second; }
void SerializedDiagnosticConsumer::addLocToRecord(SourceLoc Loc, SourceManager &SM, StringRef Filename, RecordDataImpl &Record) { if (!Loc.isValid()) { // Emit a "sentinel" location. Record.push_back((unsigned)0); // File. Record.push_back((unsigned)0); // Line. Record.push_back((unsigned)0); // Column. Record.push_back((unsigned)0); // Offset. return; } auto bufferId = SM.findBufferContainingLoc(Loc); unsigned line, col; std::tie(line, col) = SM.getLineAndColumn(Loc); Record.push_back(getEmitFile(Filename)); Record.push_back(line); Record.push_back(col); Record.push_back(SM.getLocOffsetInBuffer(Loc, bufferId)); }