CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit); if (!D) return 0; CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D); if (Index >= Diags->getNumDiagnostics()) return 0; return Diags->getDiagnostic(Index); }
CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { if (cxtu::isNotUsableTU(Unit)) { LOG_BAD_TU(Unit); return nullptr; } CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit); if (!D) return nullptr; CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D); if (Index >= Diags->getNumDiagnostics()) return nullptr; return Diags->getDiagnostic(Index); }
CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU, bool checkIfChanged) { ASTUnit *AU = static_cast<ASTUnit *>(TU->TUData); if (TU->Diagnostics && checkIfChanged) { // In normal use, ASTUnit's diagnostics should not change unless we reparse. // Currently they can only change by using the internal testing flag // '-error-on-deserialized-decl' which will error during deserialization of // a declaration. What will happen is: // // -c-index-test gets a CXTranslationUnit // -checks the diagnostics, the diagnostics set is lazily created, // no errors are reported // -later does an operation, like annotation of tokens, that triggers // -error-on-deserialized-decl, that will emit a diagnostic error, // that ASTUnit will catch and add to its stored diagnostics vector. // -c-index-test wants to check whether an error occurred after performing // the operation but can only query the lazily created set. // // We check here if a new diagnostic was appended since the last time the // diagnostic set was created, in which case we reset it. CXDiagnosticSetImpl * Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); if (AU->stored_diag_size() != Set->getNumDiagnostics()) { // Diagnostics in the ASTUnit were updated, reset the associated // diagnostics. delete Set; TU->Diagnostics = 0; } } if (!TU->Diagnostics) { CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl(); TU->Diagnostics = Set; DiagnosticOptions DOpts; CXDiagnosticRenderer Renderer(AU->getSourceManager(), AU->getASTContext().getLangOpts(), DOpts, Set); for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(), ei = AU->stored_diag_end(); it != ei; ++it) { Renderer.emitStoredDiagnostic(*it); } } return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); }
LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream, CXDiagnosticSetImpl &Diags, CXLoadedDiagnosticSetImpl &TopDiags){ if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) { reportInvalidFile("malformed diagnostic block"); return Failure; } OwningPtr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic()); RecordData Record; while (true) { unsigned blockOrCode = 0; StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block", blockOrCode); switch (Res) { case Read_EndOfStream: llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock"); case Read_Failure: return Failure; case Read_BlockBegin: { // The only blocks we care about are subdiagnostics. if (blockOrCode != serialized_diags::BLOCK_DIAG) { if (!Stream.SkipBlock()) { reportInvalidFile("Invalid subblock in Diagnostics block"); return Failure; } } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(), TopDiags)) { return Failure; } continue; } case Read_BlockEnd: Diags.appendDiagnostic(D.take()); return Success; case Read_Record: break; } // Read the record. Record.clear(); StringRef Blob; unsigned recID = Stream.readRecord(blockOrCode, Record, &Blob); if (recID < serialized_diags::RECORD_FIRST || recID > serialized_diags::RECORD_LAST) continue; switch ((serialized_diags::RecordIDs)recID) { case serialized_diags::RECORD_VERSION: continue; case serialized_diags::RECORD_CATEGORY: if (readString(TopDiags, TopDiags.Categories, "category", Record, Blob, /* allowEmptyString */ true)) return Failure; continue; case serialized_diags::RECORD_DIAG_FLAG: if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record, Blob)) return Failure; continue; case serialized_diags::RECORD_FILENAME: { if (readString(TopDiags, TopDiags.FileNames, "filename", Record, Blob)) return Failure; if (Record.size() < 3) { reportInvalidFile("Invalid file entry"); return Failure; } const FileEntry *FE = TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]], /* size */ Record[1], /* time */ Record[2]); TopDiags.Files[Record[0]] = FE; continue; } case serialized_diags::RECORD_SOURCE_RANGE: { CXSourceRange SR; if (readRange(TopDiags, Record, 0, SR)) return Failure; D->Ranges.push_back(SR); continue; } case serialized_diags::RECORD_FIXIT: { CXSourceRange SR; if (readRange(TopDiags, Record, 0, SR)) return Failure; llvm::StringRef RetStr; if (readString(TopDiags, RetStr, "FIXIT", Record, Blob, /* allowEmptyString */ true)) return Failure; D->FixIts.push_back(std::make_pair(SR, createCXString(RetStr, false))); continue; } case serialized_diags::RECORD_DIAG: { D->severity = Record[0]; unsigned offset = 1; if (readLocation(TopDiags, Record, offset, D->DiagLoc)) return Failure; D->category = Record[offset++]; unsigned diagFlag = Record[offset++]; D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : ""; D->CategoryText = D->category ? TopDiags.Categories[D->category] : ""; D->Spelling = TopDiags.makeString(Blob); continue; } } } }
void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) { CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags); if (D->isExternallyManaged()) delete D; }