12815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//===-- CXLoadedDiagnostic.cpp - Handling of persisent diags ----*- C++ -*-===// 22815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// 32815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// The LLVM Compiler Infrastructure 42815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// 52815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// This file is distributed under the University of Illinois Open Source 62815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// License. See LICENSE.TXT for details. 72815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// 82815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//===----------------------------------------------------------------------===// 92815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// 102815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// Implements handling of persisent diagnostics. 112815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner// 122815bc91cf655e84a220e69cd07c5125c028df0cChris Lattner//===----------------------------------------------------------------------===// 13153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 14153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "CXLoadedDiagnostic.h" 15153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "CXString.h" 16153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Basic/Diagnostic.h" 17153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "clang/Basic/FileManager.h" 18651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Basic/LLVM.h" 19176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Frontend/SerializedDiagnosticReader.h" 200e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/Frontend/SerializedDiagnostics.h" 21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/Optional.h" 223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h" 23153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/StringRef.h" 24153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/ADT/Twine.h" 25153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Bitcode/BitstreamReader.h" 26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/ErrorHandling.h" 27153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek#include "llvm/Support/MemoryBuffer.h" 28153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekusing namespace clang; 29153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 30153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 31153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Extend CXDiagnosticSetImpl which contains strings for diagnostics. 32153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 33153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 349ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenkotypedef llvm::DenseMap<unsigned, const char *> Strings; 35153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 36153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace { 37153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekclass CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl { 38153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekpublic: 39153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {} 4033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar ~CXLoadedDiagnosticSetImpl() override {} 41153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 42153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek llvm::BumpPtrAllocator Alloc; 43153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek Strings Categories; 44153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek Strings WarningFlags; 45153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek Strings FileNames; 46153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 47153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek FileSystemOptions FO; 48153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek FileManager FakeFiles; 49153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek llvm::DenseMap<unsigned, const FileEntry *> Files; 509ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko 519ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko /// \brief Copy the string into our own allocator. 529ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko const char *copyString(StringRef Blob) { 53b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner char *mem = Alloc.Allocate<char>(Blob.size() + 1); 54b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner memcpy(mem, Blob.data(), Blob.size()); 55b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner mem[Blob.size()] = '\0'; 569ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko return mem; 57b3ce35764adcc5749e8729709b1f3737227d90ecChris Lattner } 58153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek}; 59153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 60153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 61153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 62153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Cleanup. 63153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 64153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 65153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXLoadedDiagnostic::~CXLoadedDiagnostic() {} 66153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 67153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 68153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Public CXLoadedDiagnostic methods. 69153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 70153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 71153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const { 72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME: Fail more softly if the diagnostic level is unknown? 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines auto severityAsLevel = static_cast<serialized_diags::Level>(severity); 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(severity == static_cast<unsigned>(severityAsLevel) && 75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "unknown serialized diagnostic level"); 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines switch (severityAsLevel) { 78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#define CASE(X) case serialized_diags::X: return CXDiagnostic_##X; 79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Ignored) 80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Note) 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Warning) 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Error) 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CASE(Fatal) 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#undef CASE 856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // The 'Remark' level isn't represented in the stable API. 866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines case serialized_diags::Remark: return CXDiagnostic_Warning; 87153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 88153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 89153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek llvm_unreachable("Invalid diagnostic level"); 90153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 91153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 92153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekstatic CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) { 93153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // The lowest bit of ptr_data[0] is always set to 1 to indicate this 94153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // is a persistent diagnostic. 95153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek uintptr_t V = (uintptr_t) DLoc; 96153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek V |= 0x1; 97c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines CXSourceLocation Loc = { { (void*) V, nullptr }, 0 }; 98153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return Loc; 99153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 100153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 101153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceLocation CXLoadedDiagnostic::getLocation() const { 102153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // The lowest bit of ptr_data[0] is always set to 1 to indicate this 103153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // is a persistent diagnostic. 104153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return makeLocation(&DiagLoc); 105153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 106153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 107153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getSpelling() const { 1085595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko return cxstring::createRef(Spelling); 109153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 110153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 111153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const { 112153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (DiagOption.empty()) 113dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko return cxstring::createEmpty(); 114153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 115153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // FIXME: possibly refactor with logic in CXStoredDiagnostic. 116153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (Disable) 1175595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko *Disable = cxstring::createDup((Twine("-Wno-") + DiagOption).str()); 1185595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko return cxstring::createDup((Twine("-W") + DiagOption).str()); 119153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 120153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 121153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getCategory() const { 122153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return category; 123153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 124153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 12578d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted KremenekCXString CXLoadedDiagnostic::getCategoryText() const { 1265595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko return cxstring::createDup(CategoryText); 12778d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek} 12878d5d3bb9386a5aa31d19445eb8f81bf2652acb4Ted Kremenek 129153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumRanges() const { 130153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return Ranges.size(); 131153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 132153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 133153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const { 134153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek assert(Range < Ranges.size()); 135153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return Ranges[Range]; 136153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 137153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 138153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekunsigned CXLoadedDiagnostic::getNumFixIts() const { 139153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return FixIts.size(); 140153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 141153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 142153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXString CXLoadedDiagnostic::getFixIt(unsigned FixIt, 143153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek CXSourceRange *ReplacementRange) const { 144153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek assert(FixIt < FixIts.size()); 145153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (ReplacementRange) 146153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek *ReplacementRange = FixIts[FixIt].first; 1479ba7627d25a7555b1afff04f685d2f161974e682Dmitri Gribenko return cxstring::createRef(FixIts[FixIt].second); 148153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 149153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 150153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekvoid CXLoadedDiagnostic::decodeLocation(CXSourceLocation location, 151153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek CXFile *file, 152153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek unsigned int *line, 153153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek unsigned int *column, 154153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek unsigned int *offset) { 155153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 156153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 157153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // CXSourceLocation consists of the following fields: 158153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // 159153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // void *ptr_data[2]; 160153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // unsigned int_data; 161153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // 162153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // The lowest bit of ptr_data[0] is always set to 1 to indicate this 163153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // is a persistent diagnostic. 164153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // 165153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // For now, do the unoptimized approach and store the data in a side 166153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // data structure. We can optimize this case later. 167153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 168153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek uintptr_t V = (uintptr_t) location.ptr_data[0]; 169153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek assert((V & 0x1) == 1); 170153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek V &= ~(uintptr_t)1; 171153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 172153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek const Location &Loc = *((Location*)V); 173153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 174153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (file) 175153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek *file = Loc.file; 176153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (line) 177153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek *line = Loc.line; 178153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (column) 179153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek *column = Loc.column; 180153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (offset) 181153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek *offset = Loc.offset; 182153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 183153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 184153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 185153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek// Deserialize diagnostics. 186153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek//===----------------------------------------------------------------------===// 187153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 188153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremeneknamespace { 189176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesclass DiagLoader : serialized_diags::SerializedDiagnosticReader { 190153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek enum CXLoadDiag_Error *error; 191153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek CXString *errorString; 192176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags; 193176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags; 194176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 195176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) { 196153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (error) 197153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek *error = code; 198153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek if (errorString) 1995595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko *errorString = cxstring::createDup(err); 200176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return serialized_diags::SDError::HandlerFailed; 201153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 202153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 203176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code reportInvalidFile(llvm::StringRef err) { 204153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return reportBad(CXLoadDiag_InvalidFile, err); 205153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 206153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 207176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code readRange(const serialized_diags::Location &SDStart, 208176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const serialized_diags::Location &SDEnd, 209176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXSourceRange &SR); 210e97ac9e684aecb5fc3fb9f86da09b8bb9dc31ff4Ted Kremenek 211176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code readLocation(const serialized_diags::Location &SDLoc, 212176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXLoadedDiagnostic::Location &LoadedLoc); 213153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 214176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesprotected: 215176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitStartOfDiagnostic() override; 216176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitEndOfDiagnostic() override; 217153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 218176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override; 219153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 220176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override; 221153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 222176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitDiagnosticRecord( 223176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned Severity, const serialized_diags::Location &Location, 224176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned Category, unsigned Flag, StringRef Message) override; 225153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 226176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitFilenameRecord(unsigned ID, unsigned Size, 227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned Timestamp, 228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef Name) override; 229176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code visitFixitRecord(const serialized_diags::Location &Start, 231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const serialized_diags::Location &End, 232176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef CodeToInsert) override; 233176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 234176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code 235176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines visitSourceRangeRecord(const serialized_diags::Location &Start, 236176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const serialized_diags::Location &End) override; 237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 238176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinespublic: 239176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines DiagLoader(enum CXLoadDiag_Error *e, CXString *es) 240176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines : SerializedDiagnosticReader(), error(e), errorString(es) { 241176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (error) 242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *error = CXLoadDiag_None; 243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (errorString) 244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *errorString = cxstring::createEmpty(); 245153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXDiagnosticSet load(const char *file); 248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}; 249153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 250153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesCXDiagnosticSet DiagLoader::load(const char *file) { 252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>(); 253176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 254176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code EC = readDiagnostics(file); 255176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (EC) { 256176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines switch (EC.value()) { 257176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case static_cast<int>(serialized_diags::SDError::HandlerFailed): 258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // We've already reported the problem. 259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case static_cast<int>(serialized_diags::SDError::CouldNotLoad): 261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines reportBad(CXLoadDiag_CannotLoad, EC.message()); 262176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 263176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines default: 264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines reportInvalidFile(EC.message()); 265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 266153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return 0; 268153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return (CXDiagnosticSet)TopDiags.release(); 271153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 272153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code 274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::readLocation(const serialized_diags::Location &SDLoc, 275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXLoadedDiagnostic::Location &LoadedLoc) { 276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned FileID = SDLoc.FileID; 277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (FileID == 0) 278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines LoadedLoc.file = nullptr; 279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else { 280176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines LoadedLoc.file = const_cast<FileEntry *>(TopDiags->Files[FileID]); 281176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!LoadedLoc.file) 282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return reportInvalidFile("Corrupted file entry in source location"); 283153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 284176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines LoadedLoc.line = SDLoc.Line; 285176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines LoadedLoc.column = SDLoc.Col; 286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines LoadedLoc.offset = SDLoc.Offset; 287176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 288153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 289153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 290176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code 291176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::readRange(const serialized_diags::Location &SDStart, 292176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const serialized_diags::Location &SDEnd, 293176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXSourceRange &SR) { 294176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXLoadedDiagnostic::Location *Start, *End; 295176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Start = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>(); 296176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines End = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>(); 297176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 298176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code EC; 299176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if ((EC = readLocation(SDStart, *Start))) 300176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return EC; 301176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if ((EC = readLocation(SDEnd, *End))) 302176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return EC; 303153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 304176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXSourceLocation startLoc = makeLocation(Start); 305176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXSourceLocation endLoc = makeLocation(End); 306176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SR = clang_getRange(startLoc, endLoc); 307176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 308176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 309952538d48d75b2c01d98002a46691638f9f9a4acTed Kremenek 310176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitStartOfDiagnostic() { 311176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentDiags.push_back(llvm::make_unique<CXLoadedDiagnostic>()); 312176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 313153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 314153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 315176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitEndOfDiagnostic() { 316176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines auto D = CurrentDiags.pop_back_val(); 317176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (CurrentDiags.empty()) 318176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags->appendDiagnostic(std::move(D)); 319176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 320176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentDiags.back()->getChildDiagnostics().appendDiagnostic(std::move(D)); 321176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 322153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 323153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 324176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) { 325176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: Why do we care about long strings? 326176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Name.size() > 65536) 327176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return reportInvalidFile("Out-of-bounds string in category"); 328176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags->Categories[ID] = TopDiags->copyString(Name); 329176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 330176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 331153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 332176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitDiagFlagRecord(unsigned ID, StringRef Name) { 333176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: Why do we care about long strings? 334176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Name.size() > 65536) 335176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return reportInvalidFile("Out-of-bounds string in warning flag"); 336176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags->WarningFlags[ID] = TopDiags->copyString(Name); 337176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 338153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 339153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 340176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitFilenameRecord(unsigned ID, unsigned Size, 341176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned Timestamp, 342176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef Name) { 343176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: Why do we care about long strings? 344176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Name.size() > 65536) 345176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return reportInvalidFile("Out-of-bounds string in filename"); 346176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags->FileNames[ID] = TopDiags->copyString(Name); 347176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags->Files[ID] = 348176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines TopDiags->FakeFiles.getVirtualFile(Name, Size, Timestamp); 349176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 350153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 351153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 352176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code 353176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start, 354176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const serialized_diags::Location &End) { 355176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXSourceRange SR; 356176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (std::error_code EC = readRange(Start, End, SR)) 357176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return EC; 358176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentDiags.back()->Ranges.push_back(SR); 359176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 360176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 361153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 362176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code 363176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesDiagLoader::visitFixitRecord(const serialized_diags::Location &Start, 364176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const serialized_diags::Location &End, 365176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef CodeToInsert) { 366176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXSourceRange SR; 367176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (std::error_code EC = readRange(Start, End, SR)) 368176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return EC; 369176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: Why do we care about long strings? 370176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (CodeToInsert.size() > 65536) 371176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return reportInvalidFile("Out-of-bounds string in FIXIT"); 372176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentDiags.back()->FixIts.push_back( 373176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::make_pair(SR, TopDiags->copyString(CodeToInsert))); 374176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 375176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 377176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code DiagLoader::visitDiagnosticRecord( 378176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned Severity, const serialized_diags::Location &Location, 379176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines unsigned Category, unsigned Flag, StringRef Message) { 380176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CXLoadedDiagnostic &D = *CurrentDiags.back(); 381176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines D.severity = Severity; 382176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (std::error_code EC = readLocation(Location, D.DiagLoc)) 383176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return EC; 384176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines D.category = Category; 385176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : ""; 386176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines D.CategoryText = Category ? TopDiags->Categories[Category] : ""; 387176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines D.Spelling = TopDiags->copyString(Message); 388176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return std::error_code(); 389153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 390153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 391153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenekextern "C" { 392153221717e39ce41323d5bc6b8b8bf130923c1bdTed KremenekCXDiagnosticSet clang_loadDiagnostics(const char *file, 393153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek enum CXLoadDiag_Error *error, 394153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek CXString *errorString) { 395153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek DiagLoader L(error, errorString); 396153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek return L.load(file); 397153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 398153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} // end extern 'C'. 399