зеркало из https://github.com/github/codeql.git
Merge pull request #13991 from github/redsun82/swift-use-concepts
Swift: use C++20 constraints and concepts to simplify code
This commit is contained in:
Коммит
6d85d0d0f7
|
@ -6,7 +6,7 @@ namespace codeql {
|
||||||
{{#tags}}
|
{{#tags}}
|
||||||
|
|
||||||
// {{id}}
|
// {{id}}
|
||||||
struct {{name}}Tag {{#has_bases}}: {{#bases}}{{^first}}, {{/first}}{{base}}Tag{{/bases}} {{/has_bases}}{
|
struct {{name}}Tag {{#has_bases}}: {{#bases}}{{^first}}, {{/first}}virtual {{base}}Tag{{/bases}} {{/has_bases}}{
|
||||||
static constexpr const char* prefix = "{{name}}";
|
static constexpr const char* prefix = "{{name}}";
|
||||||
};
|
};
|
||||||
{{/tags}}
|
{{/tags}}
|
||||||
|
|
|
@ -38,19 +38,6 @@ class SwiftDispatcher {
|
||||||
const swift::PoundAvailableInfo*,
|
const swift::PoundAvailableInfo*,
|
||||||
const swift::AvailabilitySpec*>;
|
const swift::AvailabilitySpec*>;
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
static constexpr bool IsFetchable = std::is_constructible_v<Handle, const E&>;
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
static constexpr bool IsLocatable =
|
|
||||||
std::is_base_of_v<LocatableTag, TrapTagOf<E>> && !std::is_base_of_v<TypeTag, TrapTagOf<E>>;
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
static constexpr bool IsDeclPointer = std::is_convertible_v<E, const swift::Decl*>;
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
static constexpr bool IsTypePointer = std::is_convertible_v<E, const swift::TypeBase*>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// all references and pointers passed as parameters to this constructor are supposed to outlive
|
// all references and pointers passed as parameters to this constructor are supposed to outlive
|
||||||
// the SwiftDispatcher
|
// the SwiftDispatcher
|
||||||
|
@ -76,7 +63,7 @@ class SwiftDispatcher {
|
||||||
using Label = std::remove_reference_t<decltype(label)>;
|
using Label = std::remove_reference_t<decltype(label)>;
|
||||||
if (!label.valid()) {
|
if (!label.valid()) {
|
||||||
const char* action;
|
const char* action;
|
||||||
if constexpr (std::is_base_of_v<typename Label::Tag, UnspecifiedElementTag>) {
|
if constexpr (std::derived_from<UnspecifiedElementTag, typename Label::Tag>) {
|
||||||
action = "replacing with unspecified element";
|
action = "replacing with unspecified element";
|
||||||
label = emitUnspecified(idOf(entry), field, index);
|
label = emitUnspecified(idOf(entry), field, index);
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,7 +119,7 @@ class SwiftDispatcher {
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
std::optional<TrapLabel<ElementTag>> idOf(const E& entry) {
|
std::optional<TrapLabel<ElementTag>> idOf(const E& entry) {
|
||||||
if constexpr (HasId<E>::value) {
|
if constexpr (requires { entry.id; }) {
|
||||||
return entry.id;
|
return entry.id;
|
||||||
} else {
|
} else {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -142,13 +129,14 @@ class SwiftDispatcher {
|
||||||
// This method gives a TRAP label for already emitted AST node.
|
// This method gives a TRAP label for already emitted AST node.
|
||||||
// If the AST node was not emitted yet, then the emission is dispatched to a corresponding
|
// If the AST node was not emitted yet, then the emission is dispatched to a corresponding
|
||||||
// visitor (see `visit(T *)` methods below).
|
// visitor (see `visit(T *)` methods below).
|
||||||
template <typename E, std::enable_if_t<IsFetchable<E>>* = nullptr>
|
// clang-format off
|
||||||
TrapLabelOf<E> fetchLabel(const E& e, swift::Type type = {}) {
|
template <typename E>
|
||||||
if constexpr (std::is_constructible_v<bool, const E&>) {
|
requires std::constructible_from<Handle, E*>
|
||||||
if (!e) {
|
TrapLabelOf<E> fetchLabel(const E* e, swift::Type type = {}) {
|
||||||
// this will be treated on emission
|
// clang-format on
|
||||||
return undefined_label;
|
if (!e) {
|
||||||
}
|
// this will be treated on emission
|
||||||
|
return undefined_label;
|
||||||
}
|
}
|
||||||
auto& stored = store[e];
|
auto& stored = store[e];
|
||||||
if (!stored.valid()) {
|
if (!stored.valid()) {
|
||||||
|
@ -174,8 +162,11 @@ class SwiftDispatcher {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, std::enable_if_t<IsFetchable<E*>>* = nullptr>
|
// clang-format off
|
||||||
|
template <typename E>
|
||||||
|
requires std::constructible_from<Handle, E*>
|
||||||
TrapLabelOf<E> fetchLabel(const E& e) {
|
TrapLabelOf<E> fetchLabel(const E& e) {
|
||||||
|
// clang-format on
|
||||||
return fetchLabel(&e);
|
return fetchLabel(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +175,8 @@ class SwiftDispatcher {
|
||||||
auto createEntry(const E& e) {
|
auto createEntry(const E& e) {
|
||||||
auto found = store.find(&e);
|
auto found = store.find(&e);
|
||||||
CODEQL_ASSERT(found != store.end(), "createEntry called on non-fetched label");
|
CODEQL_ASSERT(found != store.end(), "createEntry called on non-fetched label");
|
||||||
auto label = TrapLabel<ConcreteTrapTagOf<E>>::unsafeCreateFromUntyped(found->second);
|
using Tag = ConcreteTrapTagOf<E>;
|
||||||
|
auto label = TrapLabel<Tag>::unsafeCreateFromUntyped(found->second);
|
||||||
if constexpr (IsLocatable<E>) {
|
if constexpr (IsLocatable<E>) {
|
||||||
locationExtractor.attachLocation(sourceManager, e, label);
|
locationExtractor.attachLocation(sourceManager, e, label);
|
||||||
}
|
}
|
||||||
|
@ -195,7 +187,8 @@ class SwiftDispatcher {
|
||||||
// an example is swift::Argument, that are created on the fly and thus have no stable pointer
|
// an example is swift::Argument, that are created on the fly and thus have no stable pointer
|
||||||
template <typename E>
|
template <typename E>
|
||||||
auto createUncachedEntry(const E& e) {
|
auto createUncachedEntry(const E& e) {
|
||||||
auto label = trap.createTypedLabel<TrapTagOf<E>>();
|
using Tag = TrapTagOf<E>;
|
||||||
|
auto label = trap.createTypedLabel<Tag>();
|
||||||
locationExtractor.attachLocation(sourceManager, &e, label);
|
locationExtractor.attachLocation(sourceManager, &e, label);
|
||||||
return TrapClassOf<E>{label};
|
return TrapClassOf<E>{label};
|
||||||
}
|
}
|
||||||
|
@ -218,7 +211,7 @@ class SwiftDispatcher {
|
||||||
auto fetchRepeatedLabels(Iterable&& arg) {
|
auto fetchRepeatedLabels(Iterable&& arg) {
|
||||||
using Label = decltype(fetchLabel(*arg.begin()));
|
using Label = decltype(fetchLabel(*arg.begin()));
|
||||||
TrapLabelVectorWrapper<typename Label::Tag> ret;
|
TrapLabelVectorWrapper<typename Label::Tag> ret;
|
||||||
if constexpr (HasSize<Iterable>::value) {
|
if constexpr (requires { arg.size(); }) {
|
||||||
ret.data.reserve(arg.size());
|
ret.data.reserve(arg.size());
|
||||||
}
|
}
|
||||||
for (auto&& e : arg) {
|
for (auto&& e : arg) {
|
||||||
|
@ -251,7 +244,7 @@ class SwiftDispatcher {
|
||||||
private:
|
private:
|
||||||
template <typename E>
|
template <typename E>
|
||||||
UntypedTrapLabel createLabel(const E& e, swift::Type type) {
|
UntypedTrapLabel createLabel(const E& e, swift::Type type) {
|
||||||
if constexpr (IsDeclPointer<E> || IsTypePointer<E>) {
|
if constexpr (requires { name(e); }) {
|
||||||
if (auto mangledName = name(e)) {
|
if (auto mangledName = name(e)) {
|
||||||
if (shouldVisit(e)) {
|
if (shouldVisit(e)) {
|
||||||
toBeVisited.emplace_back(e, type);
|
toBeVisited.emplace_back(e, type);
|
||||||
|
@ -266,7 +259,7 @@ class SwiftDispatcher {
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
bool shouldVisit(const E& e) {
|
bool shouldVisit(const E& e) {
|
||||||
if constexpr (IsDeclPointer<E>) {
|
if constexpr (std::convertible_to<E, const swift::Decl*>) {
|
||||||
encounteredModules.insert(e->getModuleContext());
|
encounteredModules.insert(e->getModuleContext());
|
||||||
if (bodyEmissionStrategy.shouldEmitDeclBody(*e)) {
|
if (bodyEmissionStrategy.shouldEmitDeclBody(*e)) {
|
||||||
extractedDeclaration(e);
|
extractedDeclaration(e);
|
||||||
|
@ -295,18 +288,6 @@ class SwiftDispatcher {
|
||||||
module->isNonSwiftModule();
|
module->isNonSwiftModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct HasSize : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct HasSize<T, decltype(std::declval<T>().size(), void())> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename = void>
|
|
||||||
struct HasId : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct HasId<T, decltype(std::declval<T>().id, void())> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename Tag, typename... Ts>
|
template <typename Tag, typename... Ts>
|
||||||
TrapLabel<Tag> fetchLabelFromUnion(const llvm::PointerUnion<Ts...> u) {
|
TrapLabel<Tag> fetchLabelFromUnion(const llvm::PointerUnion<Ts...> u) {
|
||||||
TrapLabel<Tag> ret{};
|
TrapLabel<Tag> ret{};
|
||||||
|
@ -324,7 +305,7 @@ class SwiftDispatcher {
|
||||||
// on `BraceStmt`/`IfConfigDecl` elements), we cannot encounter a standalone `TypeRepr` there,
|
// on `BraceStmt`/`IfConfigDecl` elements), we cannot encounter a standalone `TypeRepr` there,
|
||||||
// so we skip this case; extracting `TypeRepr`s here would be problematic as we would not be
|
// so we skip this case; extracting `TypeRepr`s here would be problematic as we would not be
|
||||||
// able to provide the corresponding type
|
// able to provide the corresponding type
|
||||||
if constexpr (!std::is_same_v<T, swift::TypeRepr*>) {
|
if constexpr (!std::same_as<T, swift::TypeRepr*>) {
|
||||||
if (auto e = u.template dyn_cast<T>()) {
|
if (auto e = u.template dyn_cast<T>()) {
|
||||||
output = fetchLabel(e);
|
output = fetchLabel(e);
|
||||||
return true;
|
return true;
|
||||||
|
@ -348,10 +329,8 @@ class SwiftDispatcher {
|
||||||
virtual void visit(const swift::TypeBase* type) = 0;
|
virtual void visit(const swift::TypeBase* type) = 0;
|
||||||
virtual void visit(const swift::CapturedValue* capture) = 0;
|
virtual void visit(const swift::CapturedValue* capture) = 0;
|
||||||
|
|
||||||
template <typename T, std::enable_if<!std::is_base_of_v<swift::TypeRepr, T>>* = nullptr>
|
template <typename T>
|
||||||
void visit(const T* e, swift::Type) {
|
requires(!std::derived_from<T, swift::TypeRepr>) void visit(const T* e, swift::Type) { visit(e); }
|
||||||
visit(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
const swift::SourceManager& sourceManager;
|
const swift::SourceManager& sourceManager;
|
||||||
SwiftExtractorState& state;
|
SwiftExtractorState& state;
|
||||||
|
|
|
@ -12,19 +12,24 @@
|
||||||
|
|
||||||
using namespace codeql;
|
using namespace codeql;
|
||||||
|
|
||||||
|
swift::SourceRange detail::getSourceRange(const swift::Token& token) {
|
||||||
|
const auto charRange = token.getRange();
|
||||||
|
return {charRange.getStart(), charRange.getEnd()};
|
||||||
|
}
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||||
swift::SourceLoc start,
|
const swift::SourceRange& range,
|
||||||
swift::SourceLoc end,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
TrapLabel<LocatableTag> locatableLabel) {
|
||||||
if (!start.isValid() || !end.isValid()) {
|
if (!range) {
|
||||||
// invalid locations seem to come from entities synthesized by the compiler
|
// invalid locations seem to come from entities synthesized by the compiler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto file = resolvePath(sourceManager.getDisplayNameForLoc(start));
|
auto file = resolvePath(sourceManager.getDisplayNameForLoc(range.Start));
|
||||||
DbLocation entry{{}};
|
DbLocation entry{{}};
|
||||||
entry.file = fetchFileLabel(file);
|
entry.file = fetchFileLabel(file);
|
||||||
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
|
std::tie(entry.start_line, entry.start_column) =
|
||||||
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
|
sourceManager.getLineAndColumnInBuffer(range.Start);
|
||||||
|
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(range.End);
|
||||||
SwiftMangledName locName{"loc", entry.file, ':', entry.start_line, ':', entry.start_column,
|
SwiftMangledName locName{"loc", entry.file, ':', entry.start_line, ':', entry.start_column,
|
||||||
':', entry.end_line, ':', entry.end_column};
|
':', entry.end_line, ':', entry.end_column};
|
||||||
entry.id = trap.createTypedLabel<DbLocationTag>(locName);
|
entry.id = trap.createTypedLabel<DbLocationTag>(locName);
|
||||||
|
@ -43,56 +48,6 @@ TrapLabel<FileTag> SwiftLocationExtractor::emitFile(const std::filesystem::path&
|
||||||
return fetchFileLabel(resolvePath(file));
|
return fetchFileLabel(resolvePath(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::SourceRange& range,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, range.Start, range.End, locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::CapturedValue* capture,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, capture->getLoc(), locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::IfConfigClause* clause,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, clause->Loc, locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::AvailabilitySpec* spec,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, spec->getSourceRange(), locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::KeyPathExpr::Component* component,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, component->getSourceRange().Start,
|
|
||||||
component->getSourceRange().End, locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::Token* token,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, token->getRange().getStart(), token->getRange().getEnd(),
|
|
||||||
locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
swift::SourceLoc loc,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, loc, loc, locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::DiagnosticInfo* diagInfo,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocationImpl(sourceManager, diagInfo->Loc, locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
TrapLabel<FileTag> SwiftLocationExtractor::fetchFileLabel(const std::filesystem::path& file) {
|
TrapLabel<FileTag> SwiftLocationExtractor::fetchFileLabel(const std::filesystem::path& file) {
|
||||||
if (store.count(file)) {
|
if (store.count(file)) {
|
||||||
return store[file];
|
return store[file];
|
||||||
|
|
|
@ -15,104 +15,99 @@ namespace codeql {
|
||||||
|
|
||||||
class TrapDomain;
|
class TrapDomain;
|
||||||
|
|
||||||
class SwiftLocationExtractor {
|
namespace detail {
|
||||||
template <typename Locatable, typename = void>
|
template <typename T>
|
||||||
struct HasSpecializedImplementation : std::false_type {};
|
concept HasSourceRange = requires(T e) {
|
||||||
|
e.getSourceRange();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept HasStartAndEndLoc = requires(T e) {
|
||||||
|
e.getStartLoc();
|
||||||
|
e.getEndLoc();
|
||||||
|
}
|
||||||
|
&&!(HasSourceRange<T>);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept HasOneLoc = requires(T e) {
|
||||||
|
e.getLoc();
|
||||||
|
}
|
||||||
|
&&!(HasSourceRange<T>)&&(!HasStartAndEndLoc<T>);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
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 HasOneLoc auto& locatable) {
|
||||||
|
return {locatable.getLoc()};
|
||||||
|
}
|
||||||
|
|
||||||
|
swift::SourceRange getSourceRange(const HasOneLocField auto& locatable) {
|
||||||
|
return {locatable.Loc};
|
||||||
|
}
|
||||||
|
|
||||||
|
swift::SourceRange getSourceRange(const swift::Token& token);
|
||||||
|
|
||||||
|
template <typename Locatable>
|
||||||
|
swift::SourceRange getSourceRange(const llvm::MutableArrayRef<Locatable>& 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 <typename E>
|
||||||
|
concept IsLocatable = requires(E e) {
|
||||||
|
detail::getSourceRange(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SwiftLocationExtractor {
|
||||||
public:
|
public:
|
||||||
explicit SwiftLocationExtractor(TrapDomain& trap) : trap(trap) {}
|
explicit SwiftLocationExtractor(TrapDomain& trap) : trap(trap) {}
|
||||||
|
|
||||||
TrapLabel<FileTag> emitFile(swift::SourceFile* file);
|
TrapLabel<FileTag> emitFile(swift::SourceFile* file);
|
||||||
TrapLabel<FileTag> emitFile(const std::filesystem::path& file);
|
TrapLabel<FileTag> emitFile(const std::filesystem::path& file);
|
||||||
|
|
||||||
template <typename Locatable>
|
|
||||||
void attachLocation(const swift::SourceManager& sourceManager,
|
|
||||||
const Locatable& locatable,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
attachLocation(sourceManager, &locatable, locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emits a Location TRAP entry and attaches it to a `Locatable` trap label
|
// Emits a Location TRAP entry and attaches it to a `Locatable` trap label
|
||||||
template <typename Locatable,
|
|
||||||
std::enable_if_t<!HasSpecializedImplementation<Locatable>::value>* = nullptr>
|
|
||||||
void attachLocation(const swift::SourceManager& sourceManager,
|
void attachLocation(const swift::SourceManager& sourceManager,
|
||||||
const Locatable* locatable,
|
const IsLocatable auto& locatable,
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
TrapLabel<LocatableTag> locatableLabel) {
|
||||||
attachLocationImpl(sourceManager, locatable->getStartLoc(), locatable->getEndLoc(),
|
attachLocationImpl(sourceManager, detail::getSourceRange(locatable), locatableLabel);
|
||||||
locatableLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Locatable,
|
|
||||||
std::enable_if_t<HasSpecializedImplementation<Locatable>::value>* = nullptr>
|
|
||||||
void attachLocation(const swift::SourceManager& sourceManager,
|
void attachLocation(const swift::SourceManager& sourceManager,
|
||||||
const Locatable* locatable,
|
const IsLocatable auto* locatable,
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
TrapLabel<LocatableTag> locatableLabel) {
|
||||||
attachLocationImpl(sourceManager, locatable, locatableLabel);
|
attachLocation(sourceManager, *locatable, locatableLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Emits a Location TRAP entry for a list of swift entities and attaches it to a `Locatable` trap
|
|
||||||
// label
|
|
||||||
template <typename Locatable>
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const llvm::MutableArrayRef<Locatable>* locatables,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel) {
|
|
||||||
if (locatables->empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
attachLocationImpl(sourceManager, locatables->front().getStartLoc(),
|
|
||||||
locatables->back().getEndLoc(), locatableLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
swift::SourceLoc start,
|
|
||||||
swift::SourceLoc end,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
swift::SourceLoc loc,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
||||||
const swift::SourceRange& range,
|
const swift::SourceRange& range,
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
TrapLabel<LocatableTag> locatableLabel);
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::CapturedValue* capture,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::IfConfigClause* clause,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::AvailabilitySpec* spec,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::Token* token,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::DiagnosticInfo* token,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
void attachLocationImpl(const swift::SourceManager& sourceManager,
|
|
||||||
const swift::KeyPathExpr::Component* component,
|
|
||||||
TrapLabel<LocatableTag> locatableLabel);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TrapLabel<FileTag> fetchFileLabel(const std::filesystem::path& file);
|
TrapLabel<FileTag> fetchFileLabel(const std::filesystem::path& file);
|
||||||
TrapDomain& trap;
|
TrapDomain& trap;
|
||||||
std::unordered_map<std::filesystem::path, TrapLabel<FileTag>, codeql::PathHash> store;
|
std::unordered_map<std::filesystem::path, TrapLabel<FileTag>, codeql::PathHash> store;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Locatable>
|
|
||||||
struct SwiftLocationExtractor::HasSpecializedImplementation<
|
|
||||||
Locatable,
|
|
||||||
decltype(std::declval<SwiftLocationExtractor>().attachLocationImpl(
|
|
||||||
std::declval<const swift::SourceManager&>(),
|
|
||||||
std::declval<const Locatable*>(),
|
|
||||||
std::declval<TrapLabel<LocatableTag>>()))> : std::true_type {};
|
|
||||||
|
|
||||||
} // namespace codeql
|
} // namespace codeql
|
||||||
|
|
|
@ -13,9 +13,9 @@ using namespace codeql;
|
||||||
int main() {
|
int main() {
|
||||||
std::map<const char*, std::vector<const char*>> unextracted;
|
std::map<const char*, std::vector<const char*>> unextracted;
|
||||||
|
|
||||||
#define CHECK_CLASS(KIND, CLASS, PARENT) \
|
#define CHECK_CLASS(KIND, CLASS, PARENT) \
|
||||||
if (KIND##Translator::getPolicyFor##CLASS##KIND() == TranslatorPolicy::emitUnknown) { \
|
if constexpr (KIND##Translator::getPolicyFor##CLASS##KIND() == TranslatorPolicy::emitUnknown) { \
|
||||||
unextracted[#KIND].push_back(#CLASS #KIND); \
|
unextracted[#KIND].push_back(#CLASS #KIND); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECL(CLASS, PARENT) CHECK_CLASS(Decl, CLASS, PARENT)
|
#define DECL(CLASS, PARENT) CHECK_CLASS(Decl, CLASS, PARENT)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
#include <swift/AST/ASTVisitor.h>
|
#include <swift/AST/ASTVisitor.h>
|
||||||
#include <swift/AST/TypeVisitor.h>
|
#include <swift/AST/TypeVisitor.h>
|
||||||
|
|
||||||
|
@ -18,45 +20,6 @@ class TranslatorBase {
|
||||||
: dispatcher{dispatcher}, logger{"translator/" + std::string(name)} {}
|
: dispatcher{dispatcher}, logger{"translator/" + std::string(name)} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// define by macro metaprogramming member checkers
|
|
||||||
// see https://fekir.info/post/detect-member-variables/ for technical details
|
|
||||||
#define DEFINE_TRANSLATE_CHECKER(KIND, CLASS, PARENT) \
|
|
||||||
template <typename T, typename = void> \
|
|
||||||
struct HasTranslate##CLASS##KIND : std::false_type {}; \
|
|
||||||
\
|
|
||||||
template <typename T> \
|
|
||||||
struct HasTranslate##CLASS##KIND<T, decltype((void)std::declval<T>().translate##CLASS##KIND( \
|
|
||||||
std::declval<const swift::CLASS##KIND&>()), \
|
|
||||||
void())> : std::true_type {};
|
|
||||||
|
|
||||||
DEFINE_TRANSLATE_CHECKER(Decl, , )
|
|
||||||
#define DECL(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Decl, CLASS, PARENT)
|
|
||||||
#define ABSTRACT_DECL(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Decl, CLASS, PARENT)
|
|
||||||
#include "swift/AST/DeclNodes.def"
|
|
||||||
|
|
||||||
DEFINE_TRANSLATE_CHECKER(Stmt, , )
|
|
||||||
#define STMT(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Stmt, CLASS, PARENT)
|
|
||||||
#define ABSTRACT_STMT(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Stmt, CLASS, PARENT)
|
|
||||||
#include "swift/AST/StmtNodes.def"
|
|
||||||
|
|
||||||
DEFINE_TRANSLATE_CHECKER(Expr, , )
|
|
||||||
#define EXPR(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Expr, CLASS, PARENT)
|
|
||||||
#define ABSTRACT_EXPR(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Expr, CLASS, PARENT)
|
|
||||||
#include "swift/AST/ExprNodes.def"
|
|
||||||
|
|
||||||
DEFINE_TRANSLATE_CHECKER(Pattern, , )
|
|
||||||
#define PATTERN(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Pattern, CLASS, PARENT)
|
|
||||||
#include "swift/AST/PatternNodes.def"
|
|
||||||
|
|
||||||
DEFINE_TRANSLATE_CHECKER(Type, , )
|
|
||||||
#define TYPE(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Type, CLASS, PARENT)
|
|
||||||
#define ABSTRACT_TYPE(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(Type, CLASS, PARENT)
|
|
||||||
#include "swift/AST/TypeNodes.def"
|
|
||||||
|
|
||||||
DEFINE_TRANSLATE_CHECKER(TypeRepr, , )
|
|
||||||
#define TYPEREPR(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(TypeRepr, CLASS, PARENT)
|
|
||||||
#define ABSTRACT_TYPEREPR(CLASS, PARENT) DEFINE_TRANSLATE_CHECKER(TypeRepr, CLASS, PARENT)
|
|
||||||
#include "swift/AST/TypeReprNodes.def"
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
enum class TranslatorPolicy {
|
enum class TranslatorPolicy {
|
||||||
|
@ -76,11 +39,15 @@ enum class TranslatorPolicy {
|
||||||
#define DEFINE_VISIT(KIND, CLASS, PARENT) \
|
#define DEFINE_VISIT(KIND, CLASS, PARENT) \
|
||||||
public: \
|
public: \
|
||||||
static constexpr TranslatorPolicy getPolicyFor##CLASS##KIND() { \
|
static constexpr TranslatorPolicy getPolicyFor##CLASS##KIND() { \
|
||||||
if constexpr (std::is_same_v<TrapTagOf<swift::CLASS##KIND>, void>) { \
|
if constexpr (std::same_as<TrapTagOf<swift::CLASS##KIND>, void>) { \
|
||||||
return TranslatorPolicy::ignore; \
|
return TranslatorPolicy::ignore; \
|
||||||
} else if constexpr (detail::HasTranslate##CLASS##KIND<CrtpSubclass>::value) { \
|
} else if constexpr (requires(CrtpSubclass x, swift::CLASS##KIND e) { \
|
||||||
|
x.translate##CLASS##KIND(e); \
|
||||||
|
}) { \
|
||||||
return TranslatorPolicy::translate; \
|
return TranslatorPolicy::translate; \
|
||||||
} else if constexpr (detail::HasTranslate##PARENT<CrtpSubclass>::value) { \
|
} else if constexpr (requires(CrtpSubclass x, swift::CLASS##KIND e) { \
|
||||||
|
x.translate##PARENT(e); \
|
||||||
|
}) { \
|
||||||
return TranslatorPolicy::translateParent; \
|
return TranslatorPolicy::translateParent; \
|
||||||
} else { \
|
} else { \
|
||||||
return TranslatorPolicy::emitUnknown; \
|
return TranslatorPolicy::emitUnknown; \
|
||||||
|
@ -92,7 +59,6 @@ enum class TranslatorPolicy {
|
||||||
constexpr auto policy = getPolicyFor##CLASS##KIND(); \
|
constexpr auto policy = getPolicyFor##CLASS##KIND(); \
|
||||||
if constexpr (policy == TranslatorPolicy::ignore) { \
|
if constexpr (policy == TranslatorPolicy::ignore) { \
|
||||||
LOG_ERROR("Unexpected " #CLASS #KIND); \
|
LOG_ERROR("Unexpected " #CLASS #KIND); \
|
||||||
return; \
|
|
||||||
} else if constexpr (policy == TranslatorPolicy::translate) { \
|
} else if constexpr (policy == TranslatorPolicy::translate) { \
|
||||||
dispatcher.emit(static_cast<CrtpSubclass*>(this)->translate##CLASS##KIND(*e)); \
|
dispatcher.emit(static_cast<CrtpSubclass*>(this)->translate##CLASS##KIND(*e)); \
|
||||||
} else if constexpr (policy == TranslatorPolicy::translateParent) { \
|
} else if constexpr (policy == TranslatorPolicy::translateParent) { \
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <binlog/binlog.hpp>
|
#include <binlog/binlog.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
namespace codeql {
|
namespace codeql {
|
||||||
|
|
||||||
|
@ -82,9 +83,8 @@ class TrapLabel : public UntypedTrapLabel {
|
||||||
static TrapLabel unsafeCreateFromUntyped(UntypedTrapLabel label) { return TrapLabel{label.id_}; }
|
static TrapLabel unsafeCreateFromUntyped(UntypedTrapLabel label) { return TrapLabel{label.id_}; }
|
||||||
|
|
||||||
template <typename SourceTag>
|
template <typename SourceTag>
|
||||||
TrapLabel(const TrapLabel<SourceTag>& other) : UntypedTrapLabel(other) {
|
requires std::derived_from<SourceTag, Tag> TrapLabel(const TrapLabel<SourceTag>& other)
|
||||||
static_assert(std::is_base_of_v<Tag, SourceTag>, "wrong label assignment!");
|
: UntypedTrapLabel(other) {}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// wrapper class to allow directly assigning a vector of TrapLabel<A> to a vector of
|
// wrapper class to allow directly assigning a vector of TrapLabel<A> to a vector of
|
||||||
|
@ -96,8 +96,8 @@ struct TrapLabelVectorWrapper {
|
||||||
std::vector<TrapLabel<TagParam>> data;
|
std::vector<TrapLabel<TagParam>> data;
|
||||||
|
|
||||||
template <typename DestinationTag>
|
template <typename DestinationTag>
|
||||||
|
requires std::derived_from<Tag, DestinationTag>
|
||||||
operator std::vector<TrapLabel<DestinationTag>>() && {
|
operator std::vector<TrapLabel<DestinationTag>>() && {
|
||||||
static_assert(std::is_base_of_v<DestinationTag, Tag>, "wrong label assignment!");
|
|
||||||
// reinterpret_cast is safe because TrapLabel instances differ only on the type, not the
|
// reinterpret_cast is safe because TrapLabel instances differ only on the type, not the
|
||||||
// underlying data
|
// underlying data
|
||||||
return std::move(reinterpret_cast<std::vector<TrapLabel<DestinationTag>>&>(data));
|
return std::move(reinterpret_cast<std::vector<TrapLabel<DestinationTag>>&>(data));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче