#pragma once #include #include #include #include #include #include #include #include "swift/extractor/trap/generated/TrapEntries.h" #include "swift/extractor/infra/file/PathHash.h" namespace codeql { class TrapDomain; namespace detail { template concept HasSourceRange = requires(T e) { e.getSourceRange(); }; template concept HasStartAndEndLoc = requires(T e) { e.getStartLoc(); e.getEndLoc(); } && !(HasSourceRange); template concept HasLAndRParenLoc = requires(T e) { e.getLParenLoc(); e.getRParenLoc(); } && !(HasSourceRange)&&!(HasStartAndEndLoc); template concept HasOneLoc = requires(T e) { e.getLoc(); } && !(HasSourceRange)&&(!HasStartAndEndLoc); template concept HasOneLocField = requires(T e) { e.Loc; }; swift::SourceRange getSourceRange(const HasSourceRange auto& locatable) { return locatable.getSourceRange(); } swift::SourceRange getSourceRange(const HasStartAndEndLoc auto& locatable) { if (locatable.getStartLoc() && locatable.getEndLoc()) { return {locatable.getStartLoc(), locatable.getEndLoc()}; } return {locatable.getStartLoc()}; } swift::SourceRange getSourceRange(const HasLAndRParenLoc auto& locatable) { if (locatable.getLParenLoc() && locatable.getRParenLoc()) { return {locatable.getLParenLoc(), locatable.getRParenLoc()}; } return {locatable.getLParenLoc()}; } swift::SourceRange getSourceRange(const HasOneLoc auto& locatable) { return {locatable.getLoc()}; } swift::SourceRange getSourceRange(const HasOneLocField auto& locatable) { return {locatable.Loc}; } swift::SourceRange getSourceRange(const swift::Token& token); template swift::SourceRange getSourceRange(const llvm::MutableArrayRef& locatables) { if (locatables.empty()) { return {}; } auto startRange = getSourceRange(locatables.front()); auto endRange = getSourceRange(locatables.back()); if (startRange.Start && endRange.End) { return {startRange.Start, endRange.End}; } return {startRange.Start}; } } // namespace detail template concept IsLocatable = requires(E e) { detail::getSourceRange(e); }; class SwiftLocationExtractor { public: explicit SwiftLocationExtractor(TrapDomain& trap) : trap(trap) {} TrapLabel emitFile(swift::SourceFile* file); TrapLabel emitFile(const std::filesystem::path& file); // Emits a Location TRAP entry and attaches it to a `Locatable` trap label void attachLocation(const swift::SourceManager& sourceManager, const IsLocatable auto& locatable, TrapLabel locatableLabel) { attachLocationImpl(sourceManager, detail::getSourceRange(locatable), locatableLabel); } void attachLocation(const swift::SourceManager& sourceManager, const IsLocatable auto* locatable, TrapLabel locatableLabel) { attachLocation(sourceManager, *locatable, locatableLabel); } private: void attachLocationImpl(const swift::SourceManager& sourceManager, const swift::SourceRange& range, TrapLabel locatableLabel); private: TrapLabel fetchFileLabel(const std::filesystem::path& file); TrapDomain& trap; std::unordered_map, codeql::PathHash> store; }; } // namespace codeql