#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "revng/TupleTree/TupleTreePath.h" namespace model { class Binary; } namespace revng { class LocationBase { public: virtual std::string toString() const = 0; virtual ~LocationBase() = default; }; class DocumentErrorBase : public llvm::ErrorInfo { public: inline static char ID = '0'; private: struct Entry { public: Entry(llvm::StringRef Reason, std::unique_ptr Location) : Reason(Reason.str()), Location(std::move(Location)) {} std::string Reason; std::unique_ptr Location; }; using iterator = llvm::SmallVector::iterator; using const_iterator = llvm::SmallVector::const_iterator; protected: using IDContainer = llvm::SmallVector; llvm::SmallVector Entries; IDContainer Ids; public: explicit DocumentErrorBase(const IDContainer &DerivedIds) : Entries(), Ids(std::move(DerivedIds)) { Ids.push_back(DocumentErrorBase::classID()); } DocumentErrorBase() { Ids.push_back(DocumentErrorBase::classID()); } virtual std::string getTypeName() const = 0; virtual std::string getLocationTypeName() const = 0; // Returns the class ID for this type. static const void *classID() { return &ID; } iterator begin() { return Entries.begin(); } iterator end() { return Entries.end(); } [[nodiscard]] const_iterator begin() const { return Entries.begin(); } [[nodiscard]] const_iterator end() const { return Entries.end(); } size_t size() const { return Entries.size(); } const std::string &getMessage(size_t I) const { return Entries[I].Reason; } std::string getLocation(size_t I) const { return Entries[I].Location->toString(); } virtual bool isA(const void *const ClassID) const { return llvm::find(Ids, ClassID) != Ids.end(); } public: std::error_code convertToErrorCode() const final { return llvm::inconvertibleErrorCode(); } void log(llvm::raw_ostream &OS) const final { OS << "Diff Errors\n"; for (auto &Reason : Entries) { OS << "\t" << Reason.Reason << "\n"; } } }; template class DocumentError : public DocumentErrorBase { private: static DocumentErrorBase::IDContainer getClassIds() { DocumentErrorBase::IDContainer Ids({ llvm::ErrorInfoBase::classID(), Derived::classID(), DocumentError::classID(), }); return Ids; } public: using LocationType = Location; inline static char ID = '0'; DocumentError(const DocumentErrorBase::IDContainer &Ids = getClassIds()) : DocumentErrorBase(Ids) {} DocumentError(llvm::StringRef Reason, const Location &ReasonLocation, const DocumentErrorBase::IDContainer &Ids = getClassIds()) : DocumentErrorBase(Ids) { addReason(Reason, ReasonLocation); } void addReason(llvm::StringRef NewReason, const Location &ReasonLocation) { Entries.emplace_back(NewReason.str(), std::make_unique(ReasonLocation)); } std::string getLocationTypeName() const override { return Location::getTypeName(); } public: static llvm::Error makeError(std::unique_ptr Content) { if (Content->size() != 0) return llvm::Error(std::move(Content)); return llvm::Error::success(); } public: // Returns the class ID for this type. static const void *classID() { return &Derived::ID; } }; } // namespace revng