Swift: use C++ entry style visitor in `DeclVisitor`

This commit is contained in:
Paolo Tranquilli 2022-05-19 12:40:16 +02:00
Родитель 42ec6350eb
Коммит 9231013401
8 изменённых файлов: 185 добавлений и 203 удалений

Просмотреть файл

@ -19,7 +19,7 @@ File:
name: string
Locatable:
location: Location
location: Location?
Location:
file: File

Просмотреть файл

@ -7,6 +7,7 @@
#include <vector>
#include "{{include_dir}}/{{trap_affix}}Label.h"
#include "{{include_dir}}/{{trap_affix}}TagTraits.h"
#include "./{{trap_affix}}Entries.h"
namespace {{namespace}} {
@ -54,5 +55,10 @@ struct {{name}}{{#final}} : Binding<{{name}}Tag>{{#bases}}, {{ref.name}}{{/bases
{{/fields}}
}
};
template <>
struct detail::ToTrapClassFunctor<{{name}}Tag> {
using type = {{name}};
};
{{/classes}}
}

Просмотреть файл

@ -120,6 +120,27 @@ class SwiftDispatcher {
locatableLabel);
}
// return `std::optional(fetchLabel(arg))` if arg converts to true, otherwise std::nullopt
template <typename Arg>
auto fetchOptionalLabel(Arg&& arg)
-> std::optional<decltype(fetchLabel(std::forward<Arg>(arg)))> {
if (arg) {
return fetchLabel(std::forward<Arg>(arg));
}
return std::nullopt;
}
// map `fetchLabel` on the iterable `arg`, returning a vector of all labels
template <typename Iterable>
auto fetchRepeatedLabels(Iterable&& arg) -> std::vector<decltype(fetchLabel(*arg.begin()))> {
std::vector<decltype(fetchLabel(*arg.begin()))> ret;
ret.reserve(arg.size());
for (const auto& e : arg) {
ret.push_back(fetchLabel(e));
}
return ret;
}
private:
// types to be supported by assignNewLabel/fetchLabel need to be listed here
using Store = TrapLabelStore<swift::Decl,
@ -147,7 +168,7 @@ class SwiftDispatcher {
auto locLabel = createLabel<LocationTag>('{', fileLabel, "}:", startLine, ':', startColumn, ':',
endLine, ':', endColumn);
trap.emit(LocationsTrap{locLabel, fileLabel, startLine, startColumn, endLine, endColumn});
trap.emit(LocatablesTrap{locatableLabel, locLabel});
trap.emit(LocatableLocationsTrap{locatableLabel, locLabel});
}
template <typename Tag, typename... Ts>

Просмотреть файл

@ -19,6 +19,10 @@ struct ToTagOverride : ToTagFunctor<T> {};
// must be instantiated to map trap labels to the corresponding generated binding trap entry
template <typename Label>
struct ToBindingTrapFunctor;
// must be instantiated to map trap tags to the corresponding generated trap class
template <typename Tag>
struct ToTrapClassFunctor;
} // namespace detail
template <typename T>
@ -30,4 +34,7 @@ using TrapLabelOf = TrapLabel<TrapTagOf<T>>;
template <typename T>
using BindingTrapOf = typename detail::ToBindingTrapFunctor<TrapLabelOf<T>>::type;
template <typename T>
using TrapClassOf = typename detail::ToTrapClassFunctor<TrapTagOf<T>>::type;
} // namespace codeql

Просмотреть файл

@ -9,294 +9,218 @@
namespace codeql {
// `swift::Decl` visitor
// public `visitXXX(swift::XXX* decl)` methods visit concrete declarations
// private `emitXXX(swift::XXX* decl, TrapLabel<XXXTag> label)` are used to fill the properties
// related to an abstract `XXX` entity, given the label assigned to the concrete entry
// In general, `visitXXX/emitXXX` should call `emitYYY` with `YYY` the direct superclass of `XXX`
// (if not `Decl` itself)
// TODO: maybe make the above chain of calls automatic with a bit of macro metaprogramming?
class DeclVisitor : public AstVisitorBase<DeclVisitor> {
public:
using AstVisitorBase<DeclVisitor>::AstVisitorBase;
void visitFuncDecl(swift::FuncDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ConcreteFuncDeclsTrap{label});
emitAbstractFunctionDecl(decl, label);
void translateFuncDecl(swift::FuncDecl* decl, codeql::ConcreteFuncDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillAbstractFunctionDecl(decl, entry);
}
void visitConstructorDecl(swift::ConstructorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ConstructorDeclsTrap{label});
emitConstructorDecl(decl, label);
void translateConstructorDecl(swift::ConstructorDecl* decl, codeql::ConstructorDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillAbstractFunctionDecl(decl, entry);
}
void visitDestructorDecl(swift::DestructorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(DestructorDeclsTrap{label});
emitDestructorDecl(decl, label);
void translateDestructorDecl(swift::DestructorDecl* decl, codeql::DestructorDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillAbstractFunctionDecl(decl, entry);
}
void visitPrefixOperatorDecl(swift::PrefixOperatorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PrefixOperatorDeclsTrap{label});
emitOperatorDecl(decl, label);
void translatePrefixOperatorDecl(swift::PrefixOperatorDecl* decl,
codeql::PrefixOperatorDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillOperatorDecl(decl, entry);
}
void visitPostfixOperatorDecl(swift::PostfixOperatorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PostfixOperatorDeclsTrap{label});
emitOperatorDecl(decl, label);
void translatePostfixOperatorDecl(swift::PostfixOperatorDecl* decl,
codeql::PostfixOperatorDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillOperatorDecl(decl, entry);
}
void visitInfixOperatorDecl(swift::InfixOperatorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(InfixOperatorDeclsTrap{label});
if (auto group = decl->getPrecedenceGroup()) {
dispatcher_.emit(InfixOperatorDeclPrecedenceGroupsTrap{label, dispatcher_.fetchLabel(group)});
}
emitOperatorDecl(decl, label);
void translateInfixOperatorDecl(swift::InfixOperatorDecl* decl,
codeql::InfixOperatorDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
entry->precedence_group = dispatcher_.fetchOptionalLabel(decl->getPrecedenceGroup());
fillOperatorDecl(decl, entry);
}
void visitPrecedenceGroupDecl(swift::PrecedenceGroupDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PrecedenceGroupDeclsTrap{label});
void translatePrecedenceGroupDecl(swift::PrecedenceGroupDecl* decl,
codeql::PrecedenceGroupDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
}
void visitParamDecl(swift::ParamDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ParamDeclsTrap{label});
emitVarDecl(decl, label);
void translateParamDecl(swift::ParamDecl* decl, codeql::ParamDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillAbstractVarDecl(decl, entry);
}
void visitTopLevelCodeDecl(swift::TopLevelCodeDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
void translateTopLevelCodeDecl(swift::TopLevelCodeDecl* decl, codeql::TopLevelCodeDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
assert(decl->getBody() && "Expect top level code to have body");
dispatcher_.emit(TopLevelCodeDeclsTrap{label, dispatcher_.fetchLabel(decl->getBody())});
entry->body = dispatcher_.fetchLabel(decl->getBody());
}
void visitPatternBindingDecl(swift::PatternBindingDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PatternBindingDeclsTrap{label});
void translatePatternBindingDecl(swift::PatternBindingDecl* decl,
codeql::PatternBindingDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
for (unsigned i = 0; i < decl->getNumPatternEntries(); ++i) {
auto pattern = decl->getPattern(i);
assert(pattern && "Expect pattern binding decl to have all patterns");
dispatcher_.emit(PatternBindingDeclPatternsTrap{label, i, dispatcher_.fetchLabel(pattern)});
if (auto init = decl->getInit(i)) {
dispatcher_.emit(PatternBindingDeclInitsTrap{label, i, dispatcher_.fetchLabel(init)});
}
entry->patterns.push_back(dispatcher_.fetchLabel(pattern));
entry->inits.push_back(dispatcher_.fetchOptionalLabel(decl->getInit(i)));
}
}
void visitVarDecl(swift::VarDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
auto introducer = static_cast<uint8_t>(decl->getIntroducer());
dispatcher_.emit(ConcreteVarDeclsTrap{label, introducer});
emitVarDecl(decl, label);
void translateVarDecl(swift::VarDecl* decl, codeql::ConcreteVarDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
entry->introducer_int = static_cast<uint8_t>(decl->getIntroducer());
fillAbstractVarDecl(decl, entry);
}
void visitStructDecl(swift::StructDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(StructDeclsTrap{label});
emitNominalTypeDecl(decl, label);
void translateStructDecl(swift::StructDecl* decl, codeql::StructDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillNominalTypeDecl(decl, entry);
}
void visitClassDecl(swift::ClassDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ClassDeclsTrap{label});
emitNominalTypeDecl(decl, label);
void translateClassDecl(swift::ClassDecl* decl, codeql::ClassDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillNominalTypeDecl(decl, entry);
}
void visitEnumDecl(swift::EnumDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(EnumDeclsTrap{label});
emitNominalTypeDecl(decl, label);
void translateEnumDecl(swift::EnumDecl* decl, codeql::EnumDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillNominalTypeDecl(decl, entry);
}
void visitProtocolDecl(swift::ProtocolDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ProtocolDeclsTrap{label});
emitNominalTypeDecl(decl, label);
void translateProtocolDecl(swift::ProtocolDecl* decl, codeql::ProtocolDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillNominalTypeDecl(decl, entry);
}
void visitEnumCaseDecl(swift::EnumCaseDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(EnumCaseDeclsTrap{label});
auto i = 0u;
for (auto e : decl->getElements()) {
dispatcher_.emit(EnumCaseDeclElementsTrap{label, i++, dispatcher_.fetchLabel(e)});
}
void translateEnumCaseDecl(swift::EnumCaseDecl* decl, codeql::EnumCaseDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
entry->elements = dispatcher_.fetchRepeatedLabels(decl->getElements());
}
void visitEnumElementDecl(swift::EnumElementDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(EnumElementDeclsTrap{label, decl->getNameStr().str()});
void translateEnumElementDecl(swift::EnumElementDecl* decl, codeql::EnumElementDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
entry->name = decl->getNameStr().str();
if (decl->hasParameterList()) {
auto i = 0u;
for (auto p : *decl->getParameterList()) {
dispatcher_.emit(EnumElementDeclParamsTrap{label, i++, dispatcher_.fetchLabel(p)});
}
entry->params = dispatcher_.fetchRepeatedLabels(*decl->getParameterList());
}
fillValueDecl(decl, entry);
}
void visitGenericTypeParamDecl(swift::GenericTypeParamDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(GenericTypeParamDeclsTrap{label});
emitTypeDecl(decl, label);
void translateGenericTypeParamDecl(swift::GenericTypeParamDecl* decl,
GenericTypeParamDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillTypeDecl(decl, entry);
}
void visitAssociatedTypeDecl(swift::AssociatedTypeDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(AssociatedTypeDeclsTrap{label});
emitTypeDecl(decl, label);
void translateAssociatedTypeDecl(swift::AssociatedTypeDecl* decl,
codeql::AssociatedTypeDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillTypeDecl(decl, entry);
}
void visitTypeAliasDecl(swift::TypeAliasDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(TypeAliasDeclsTrap{label});
emitTypeDecl(decl, label);
void translateTypeAliasDecl(swift::TypeAliasDecl* decl, codeql::TypeAliasDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
fillTypeDecl(decl, entry);
}
void visitAccessorDecl(swift::AccessorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(AccessorDeclsTrap{label});
void translateAccessorDecl(swift::AccessorDecl* decl, codeql::AccessorDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
switch (decl->getAccessorKind()) {
case swift::AccessorKind::Get:
dispatcher_.emit(AccessorDeclIsGetterTrap{label});
entry->is_getter = true;
break;
case swift::AccessorKind::Set:
dispatcher_.emit(AccessorDeclIsSetterTrap{label});
entry->is_setter = true;
break;
case swift::AccessorKind::WillSet:
dispatcher_.emit(AccessorDeclIsWillSetTrap{label});
entry->is_will_set = true;
break;
case swift::AccessorKind::DidSet:
dispatcher_.emit(AccessorDeclIsDidSetTrap{label});
entry->is_did_set = true;
break;
}
emitAccessorDecl(decl, label);
fillAbstractFunctionDecl(decl, entry);
}
void visitSubscriptDecl(swift::SubscriptDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
auto elementTypeLabel = dispatcher_.fetchLabel(decl->getElementInterfaceType());
dispatcher_.emit(SubscriptDeclsTrap{label, elementTypeLabel});
void translateSubscriptDecl(swift::SubscriptDecl* decl, codeql::SubscriptDecl* entry) {
entry->id = dispatcher_.assignNewLabel(decl);
entry->element_type = dispatcher_.fetchLabel(decl->getElementInterfaceType());
if (auto indices = decl->getIndices()) {
for (auto i = 0u; i < indices->size(); ++i) {
dispatcher_.emit(
SubscriptDeclParamsTrap{label, i, dispatcher_.fetchLabel(indices->get(i))});
}
entry->params = dispatcher_.fetchRepeatedLabels(*indices);
}
emitAbstractStorageDecl(decl, label);
fillAbstractStorageDecl(decl, entry);
}
private:
void emitConstructorDecl(swift::ConstructorDecl* decl, TrapLabel<ConstructorDeclTag> label) {
emitAbstractFunctionDecl(decl, label);
}
void emitDestructorDecl(swift::DestructorDecl* decl, TrapLabel<DestructorDeclTag> label) {
emitAbstractFunctionDecl(decl, label);
}
void emitAbstractFunctionDecl(swift::AbstractFunctionDecl* decl,
TrapLabel<AbstractFunctionDeclTag> label) {
void fillAbstractFunctionDecl(swift::AbstractFunctionDecl* decl,
codeql::AbstractFunctionDecl* entry) {
assert(decl->hasParameterList() && "Expect functions to have a parameter list");
auto name = !decl->hasName() || decl->getName().isSpecial() ? "(unnamed function decl)"
: decl->getNameStr().str();
dispatcher_.emit(AbstractFunctionDeclsTrap{label, name});
if (auto body = decl->getBody()) {
dispatcher_.emit(AbstractFunctionDeclBodiesTrap{label, dispatcher_.fetchLabel(body)});
}
auto params = decl->getParameters();
for (auto i = 0u; i < params->size(); ++i) {
dispatcher_.emit(
AbstractFunctionDeclParamsTrap{label, i, dispatcher_.fetchLabel(params->get(i))});
}
emitValueDecl(decl, label);
emitGenericContext(decl, label);
entry->name = !decl->hasName() || decl->getName().isSpecial() ? "(unnamed function decl)"
: decl->getNameStr().str();
entry->body = dispatcher_.fetchOptionalLabel(decl->getBody());
entry->params = dispatcher_.fetchRepeatedLabels(*decl->getParameters());
fillValueDecl(decl, entry);
fillGenericContext(decl, entry);
}
void emitOperatorDecl(swift::OperatorDecl* decl, TrapLabel<OperatorDeclTag> label) {
dispatcher_.emit(OperatorDeclsTrap{label, decl->getName().str().str()});
void fillOperatorDecl(swift::OperatorDecl* decl, codeql::OperatorDecl* entry) {
entry->name = decl->getName().str().str();
}
void emitTypeDecl(swift::TypeDecl* decl, TrapLabel<TypeDeclTag> label) {
dispatcher_.emit(TypeDeclsTrap{label, decl->getNameStr().str()});
auto i = 0u;
void fillTypeDecl(swift::TypeDecl* decl, codeql::TypeDecl* entry) {
entry->name = decl->getNameStr().str();
for (auto& typeLoc : decl->getInherited()) {
auto type = typeLoc.getType();
if (type.isNull()) {
continue;
if (auto type = typeLoc.getType()) {
entry->base_types.push_back(dispatcher_.fetchLabel(type));
}
dispatcher_.emit(TypeDeclBaseTypesTrap{label, i++, dispatcher_.fetchLabel(type)});
}
emitValueDecl(decl, label);
fillValueDecl(decl, entry);
}
void emitIterableDeclContext(swift::IterableDeclContext* decl,
TrapLabel<IterableDeclContextTag> label) {
auto i = 0u;
for (auto& member : decl->getAllMembers()) {
dispatcher_.emit(IterableDeclContextMembersTrap{label, i++, dispatcher_.fetchLabel(member)});
}
void fillIterableDeclContext(swift::IterableDeclContext* decl,
codeql::IterableDeclContext* entry) {
entry->members = dispatcher_.fetchRepeatedLabels(decl->getAllMembers());
}
void emitVarDecl(swift::VarDecl* decl, TrapLabel<VarDeclTag> label) {
auto typeLabel = dispatcher_.fetchLabel(decl->getType());
dispatcher_.emit(VarDeclsTrap{label, decl->getNameStr().str(), typeLabel});
if (auto pattern = decl->getParentPattern()) {
dispatcher_.emit(VarDeclParentPatternsTrap{label, dispatcher_.fetchLabel(pattern)});
}
if (auto init = decl->getParentInitializer()) {
dispatcher_.emit(VarDeclParentInitializersTrap{label, dispatcher_.fetchLabel(init)});
}
void fillAbstractVarDecl(swift::VarDecl* decl, codeql::VarDecl* entry) {
entry->type = dispatcher_.fetchLabel(decl->getType());
entry->parent_pattern = dispatcher_.fetchOptionalLabel(decl->getParentPattern());
entry->parent_initializer = dispatcher_.fetchOptionalLabel(decl->getParentInitializer());
if (decl->hasAttachedPropertyWrapper()) {
if (auto propertyType = decl->getPropertyWrapperBackingPropertyType();
!propertyType.isNull()) {
dispatcher_.emit(
VarDeclAttachedPropertyWrapperTypesTrap{label, dispatcher_.fetchLabel(propertyType)});
}
entry->attached_property_wrapper_type =
dispatcher_.fetchOptionalLabel(decl->getPropertyWrapperBackingPropertyType());
}
emitAbstractStorageDecl(decl, label);
fillAbstractStorageDecl(decl, entry);
}
void emitNominalTypeDecl(swift::NominalTypeDecl* decl, TrapLabel<NominalTypeDeclTag> label) {
auto typeLabel = dispatcher_.fetchLabel(decl->getDeclaredType());
dispatcher_.emit(NominalTypeDeclsTrap{label, typeLabel});
emitGenericContext(decl, label);
emitIterableDeclContext(decl, label);
emitTypeDecl(decl, label);
void fillNominalTypeDecl(swift::NominalTypeDecl* decl, codeql::NominalTypeDecl* entry) {
entry->type = dispatcher_.fetchLabel(decl->getDeclaredType());
fillGenericContext(decl, entry);
fillIterableDeclContext(decl, entry);
fillTypeDecl(decl, entry);
}
void emitGenericContext(const swift::GenericContext* decl, TrapLabel<GenericContextTag> label) {
void fillGenericContext(swift::GenericContext* decl, codeql::GenericContext* entry) {
if (auto params = decl->getGenericParams()) {
auto i = 0u;
for (auto t : *params) {
dispatcher_.emit(
GenericContextGenericTypeParamsTrap{label, i++, dispatcher_.fetchLabel(t)});
}
entry->generic_type_params = dispatcher_.fetchRepeatedLabels(*params);
}
}
void emitValueDecl(const swift::ValueDecl* decl, TrapLabel<ValueDeclTag> label) {
void fillValueDecl(swift::ValueDecl* decl, codeql::ValueDecl* entry) {
assert(decl->getInterfaceType() && "Expect ValueDecl to have InterfaceType");
dispatcher_.emit(ValueDeclsTrap{label, dispatcher_.fetchLabel(decl->getInterfaceType())});
entry->interface_type = dispatcher_.fetchLabel(decl->getInterfaceType());
}
void emitAccessorDecl(swift::AccessorDecl* decl, TrapLabel<AccessorDeclTag> label) {
emitAbstractFunctionDecl(decl, label);
}
void emitAbstractStorageDecl(const swift::AbstractStorageDecl* decl,
TrapLabel<AbstractStorageDeclTag> label) {
auto i = 0u;
for (auto acc : decl->getAllAccessors()) {
dispatcher_.emit(
AbstractStorageDeclAccessorDeclsTrap{label, i++, dispatcher_.fetchLabel(acc)});
}
emitValueDecl(decl, label);
void fillAbstractStorageDecl(swift::AbstractStorageDecl* decl,
codeql::AbstractStorageDecl* entry) {
entry->accessor_decls = dispatcher_.fetchRepeatedLabels(decl->getAllAccessors());
fillValueDecl(decl, entry);
}
};

Просмотреть файл

@ -21,14 +21,34 @@ class VisitorBase {
// we want to override the default swift visitor behaviour of chaining calls to immediate
// superclasses by default and instead provide our own TBD default (using the exact type)
#define DEFAULT(KIND, CLASS, PARENT) \
void visit##CLASS##KIND(swift::CLASS##KIND* e) { dispatcher_.emitUnknown(e); }
// if we the implementation class has translate##CLASS##KIND (that uses generated C++ classes), we
// want to use that. We detect that by comparing the member function pointer to the one for a
// private undefined member function of the same name and signature in {Ast,Type}VisitorBase, which
// will be shadowed (and thus different) in case the implementation class has it.
#define DEFAULT(KIND, CLASS, PARENT) \
public: \
void visit##CLASS##KIND(swift::CLASS##KIND* e) { \
constexpr bool hasTranslateImplementation = \
(&Self::translate##CLASS##KIND != &CrtpSubclass::translate##CLASS##KIND); \
if constexpr (hasTranslateImplementation) { \
TrapClassOf<swift::CLASS##KIND> entry{}; \
static_cast<CrtpSubclass*>(this)->translate##CLASS##KIND(e, &entry); \
dispatcher_.emit(entry); \
} else { \
dispatcher_.emitUnknown(e); \
} \
} \
\
private: \
void translate##CLASS##KIND(swift::CLASS##KIND*, TrapClassOf<swift::CLASS##KIND>*);
// base class for our AST visitors, getting a SwiftDispatcher member and default emission for
// unknown/TBD entities. Like `swift::ASTVisitor`, this uses CRTP (the Curiously Recurring Template
// Pattern)
template <typename CrtpSubclass>
class AstVisitorBase : public swift::ASTVisitor<CrtpSubclass>, protected detail::VisitorBase {
using Self = AstVisitorBase;
public:
using VisitorBase::VisitorBase;
@ -53,6 +73,8 @@ class AstVisitorBase : public swift::ASTVisitor<CrtpSubclass>, protected detail:
// Pattern)
template <typename CrtpSubclass>
class TypeVisitorBase : public swift::TypeVisitor<CrtpSubclass>, protected detail::VisitorBase {
using Self = TypeVisitorBase;
public:
using VisitorBase::VisitorBase;

Просмотреть файл

@ -5,8 +5,10 @@ import codeql.swift.elements.Location
class LocatableBase extends @locatable, Element {
Location getLocation() {
exists(Location x |
locatables(this, x) and
locatable_locations(this, x) and
result = x.resolve()
)
}
predicate hasLocation() { exists(getLocation()) }
}

Просмотреть файл

@ -38,7 +38,7 @@ files(
;
#keyset[id]
locatables(
locatable_locations(
int id: @locatable ref,
int location: @location ref
);