Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion misc/codegen/templates/trap_tags_h.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace codeql {
{{#tags}}

// {{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}}";
};
{{/tags}}
Expand Down
69 changes: 24 additions & 45 deletions swift/extractor/infra/SwiftDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,6 @@ class SwiftDispatcher {
const swift::PoundAvailableInfo*,
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:
// all references and pointers passed as parameters to this constructor are supposed to outlive
// the SwiftDispatcher
Expand All @@ -76,7 +63,7 @@ class SwiftDispatcher {
using Label = std::remove_reference_t<decltype(label)>;
if (!label.valid()) {
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";
label = emitUnspecified(idOf(entry), field, index);
} else {
Expand Down Expand Up @@ -132,7 +119,7 @@ class SwiftDispatcher {

template <typename E>
std::optional<TrapLabel<ElementTag>> idOf(const E& entry) {
if constexpr (HasId<E>::value) {
if constexpr (requires { entry.id; }) {
return entry.id;
} else {
return std::nullopt;
Expand All @@ -142,13 +129,14 @@ class SwiftDispatcher {
// 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
// visitor (see `visit(T *)` methods below).
template <typename E, std::enable_if_t<IsFetchable<E>>* = nullptr>
TrapLabelOf<E> fetchLabel(const E& e, swift::Type type = {}) {
if constexpr (std::is_constructible_v<bool, const E&>) {
if (!e) {
// this will be treated on emission
return undefined_label;
}
// clang-format off
template <typename E>
requires std::constructible_from<Handle, E*>
TrapLabelOf<E> fetchLabel(const E* e, swift::Type type = {}) {
// clang-format on
if (!e) {
// this will be treated on emission
return undefined_label;
}
auto& stored = store[e];
if (!stored.valid()) {
Expand All @@ -174,8 +162,11 @@ class SwiftDispatcher {
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) {
// clang-format on
return fetchLabel(&e);
}

Expand All @@ -184,7 +175,8 @@ class SwiftDispatcher {
auto createEntry(const E& e) {
auto found = store.find(&e);
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>) {
locationExtractor.attachLocation(sourceManager, e, label);
}
Expand All @@ -195,7 +187,8 @@ class SwiftDispatcher {
// an example is swift::Argument, that are created on the fly and thus have no stable pointer
template <typename 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);
return TrapClassOf<E>{label};
}
Expand All @@ -218,7 +211,7 @@ class SwiftDispatcher {
auto fetchRepeatedLabels(Iterable&& arg) {
using Label = decltype(fetchLabel(*arg.begin()));
TrapLabelVectorWrapper<typename Label::Tag> ret;
if constexpr (HasSize<Iterable>::value) {
if constexpr (requires { arg.size(); }) {
ret.data.reserve(arg.size());
}
for (auto&& e : arg) {
Expand Down Expand Up @@ -251,7 +244,7 @@ class SwiftDispatcher {
private:
template <typename E>
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 (shouldVisit(e)) {
toBeVisited.emplace_back(e, type);
Expand All @@ -266,7 +259,7 @@ class SwiftDispatcher {

template <typename E>
bool shouldVisit(const E& e) {
if constexpr (IsDeclPointer<E>) {
if constexpr (std::convertible_to<E, const swift::Decl*>) {
encounteredModules.insert(e->getModuleContext());
if (bodyEmissionStrategy.shouldEmitDeclBody(*e)) {
extractedDeclaration(e);
Expand Down Expand Up @@ -295,18 +288,6 @@ class SwiftDispatcher {
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>
TrapLabel<Tag> fetchLabelFromUnion(const llvm::PointerUnion<Ts...> u) {
TrapLabel<Tag> ret{};
Expand All @@ -324,7 +305,7 @@ class SwiftDispatcher {
// 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
// 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>()) {
output = fetchLabel(e);
return true;
Expand All @@ -348,10 +329,8 @@ class SwiftDispatcher {
virtual void visit(const swift::TypeBase* type) = 0;
virtual void visit(const swift::CapturedValue* capture) = 0;

template <typename T, std::enable_if<!std::is_base_of_v<swift::TypeRepr, T>>* = nullptr>
void visit(const T* e, swift::Type) {
visit(e);
}
template <typename T>
requires(!std::derived_from<T, swift::TypeRepr>) void visit(const T* e, swift::Type) { visit(e); }

const swift::SourceManager& sourceManager;
SwiftExtractorState& state;
Expand Down
67 changes: 11 additions & 56 deletions swift/extractor/infra/SwiftLocationExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@

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,
swift::SourceLoc start,
swift::SourceLoc end,
const swift::SourceRange& range,
TrapLabel<LocatableTag> locatableLabel) {
if (!start.isValid() || !end.isValid()) {
if (!range) {
// invalid locations seem to come from entities synthesized by the compiler
return;
}
auto file = resolvePath(sourceManager.getDisplayNameForLoc(start));
auto file = resolvePath(sourceManager.getDisplayNameForLoc(range.Start));
DbLocation entry{{}};
entry.file = fetchFileLabel(file);
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
std::tie(entry.start_line, entry.start_column) =
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,
':', entry.end_line, ':', entry.end_column};
entry.id = trap.createTypedLabel<DbLocationTag>(locName);
Expand All @@ -43,56 +48,6 @@ TrapLabel<FileTag> SwiftLocationExtractor::emitFile(const std::filesystem::path&
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) {
if (store.count(file)) {
return store[file];
Expand Down
Loading