Merge branch 'main' into fix-history

This commit is contained in:
Arthur Baars
2022-05-20 17:20:42 +02:00
committed by GitHub
134 changed files with 3143 additions and 318 deletions

View File

@@ -35,8 +35,12 @@ def is_windows():
return True
return False
# kotlinc might be kotlinc.bat or kotlinc.cmd on Windows, so we use `which` to find out what it is
kotlinc = shutil.which('kotlinc')
if kotlinc is None:
print("Cannot build the Kotlin extractor: no kotlinc found on your PATH", file = sys.stderr)
sys.exit(1)
kotlinc = 'kotlinc.bat' if is_windows() else 'kotlinc'
javac = 'javac'
kotlin_dependency_folder = args.dependencies
@@ -201,10 +205,6 @@ def compile_standalone(version):
'build/temp_src',
version)
if shutil.which(kotlinc) == None:
print("Cannot build the Kotlin extractor: no '%s' found on your PATH" % kotlinc, file = sys.stderr)
sys.exit(1)
if args.many:
for version in kotlin_plugin_versions.many_versions:
compile_standalone(version)

View File

@@ -1,5 +1,6 @@
import platform
import re
import shutil
import subprocess
import sys
@@ -26,11 +27,11 @@ class KotlincNotFoundException(Exception):
pass
def get_single_version(fakeVersionOutput = None):
# TODO: `shell=True` is a workaround to get CI working on Windows. It breaks the build on Linux.
try:
versionOutput = subprocess.run(['kotlinc', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=is_windows()).stderr if fakeVersionOutput is None else fakeVersionOutput
except FileNotFoundError as e:
raise KotlincNotFoundException(e)
# kotlinc might be kotlinc.bat or kotlinc.cmd on Windows, so we use `which` to find out what it is
kotlinc = shutil.which('kotlinc')
if kotlinc is None:
raise KotlincNotFoundException()
versionOutput = subprocess.run([kotlinc, '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True).stderr if fakeVersionOutput is None else fakeVersionOutput
m = re.match(r'.* kotlinc-jvm ([0-9]+\.[0-9]+\.[0-9]+) .*', versionOutput)
if m is None:
raise Exception('Cannot detect version of kotlinc (got ' + str(versionOutput) + ')')

View File

@@ -21,7 +21,7 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
fun extractLater(d: IrDeclaration, signature: String): Boolean {
if (d !is IrClass && !isExternalFileClassMember(d)) {
logger.warnElement("External declaration is neither a class, nor a top-level declaration", d)
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
return false
}
val ret = externalDeclsDone.add(d)
@@ -64,7 +64,7 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
val containingClass = getContainingClassOrSelf(irDecl)
if (containingClass == null) {
logger.warnElement("Unable to get containing class", irDecl)
logger.errorElement("Unable to get containing class", irDecl)
return
}
val binaryPath = getIrClassBinaryPath(containingClass)

View File

@@ -270,7 +270,7 @@ open class KotlinFileExtractor(
if (kind == ClassKind.ENUM_CLASS) {
tw.writeIsEnumType(classId)
} else if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT) {
logger.warnElement("Unrecognised class kind $kind", c)
logger.errorElement("Unrecognised class kind $kind", c)
}
}
@@ -549,7 +549,7 @@ open class KotlinFileExtractor(
val constructorId = useFunction<DbConstructor>(enclosingConstructor)
val enclosingClass = enclosingConstructor.parentClassOrNull
if (enclosingClass == null) {
logger.warnElement("Constructor's parent is not a class", enclosingConstructor)
logger.errorElement("Constructor's parent is not a class", enclosingConstructor)
return
}
@@ -807,13 +807,13 @@ open class KotlinFileExtractor(
}
} else {
if (p.modality != Modality.FINAL || !isExternalDeclaration(p)) {
logger.errorElement("IrProperty without a getter", p)
logger.warnElement("IrProperty without a getter", p)
}
}
if (setter != null) {
if (!p.isVar) {
logger.errorElement("!isVar property with a setter", p)
logger.warnElement("!isVar property with a setter", p)
}
val setterId = extractFunction(setter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast<DbMethod>()
if (setterId != null) {
@@ -821,7 +821,7 @@ open class KotlinFileExtractor(
}
} else {
if (p.isVar && !isExternalDeclaration(p)) {
logger.errorElement("isVar property without a setter", p)
logger.warnElement("isVar property without a setter", p)
}
}
@@ -1657,7 +1657,7 @@ open class KotlinFileExtractor(
// as they can't be extracted as external dependencies.
isBuiltinCallInternal(c, "less") -> {
if(c.origin != IrStatementOrigin.LT) {
logger.errorElement("Unexpected origin for LT: ${c.origin}", c)
logger.warnElement("Unexpected origin for LT: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbLtexpr>()
val type = useType(c.type)
@@ -1667,7 +1667,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "lessOrEqual") -> {
if(c.origin != IrStatementOrigin.LTEQ) {
logger.errorElement("Unexpected origin for LTEQ: ${c.origin}", c)
logger.warnElement("Unexpected origin for LTEQ: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbLeexpr>()
val type = useType(c.type)
@@ -1677,7 +1677,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "greater") -> {
if(c.origin != IrStatementOrigin.GT) {
logger.errorElement("Unexpected origin for GT: ${c.origin}", c)
logger.warnElement("Unexpected origin for GT: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbGtexpr>()
val type = useType(c.type)
@@ -1687,7 +1687,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "greaterOrEqual") -> {
if(c.origin != IrStatementOrigin.GTEQ) {
logger.errorElement("Unexpected origin for GTEQ: ${c.origin}", c)
logger.warnElement("Unexpected origin for GTEQ: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbGeexpr>()
val type = useType(c.type)
@@ -1697,7 +1697,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "EQEQ") -> {
if(c.origin != IrStatementOrigin.EQEQ) {
logger.errorElement("Unexpected origin for EQEQ: ${c.origin}", c)
logger.warnElement("Unexpected origin for EQEQ: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbValueeqexpr>()
val type = useType(c.type)
@@ -1707,7 +1707,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "EQEQEQ") -> {
if(c.origin != IrStatementOrigin.EQEQEQ) {
logger.errorElement("Unexpected origin for EQEQEQ: ${c.origin}", c)
logger.warnElement("Unexpected origin for EQEQEQ: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbEqexpr>()
val type = useType(c.type)
@@ -1717,7 +1717,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "ieee754equals") -> {
if(c.origin != IrStatementOrigin.EQEQ) {
logger.errorElement("Unexpected origin for ieee754equals: ${c.origin}", c)
logger.warnElement("Unexpected origin for ieee754equals: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbEqexpr>()
val type = useType(c.type)
@@ -1727,7 +1727,7 @@ open class KotlinFileExtractor(
}
isBuiltinCallInternal(c, "CHECK_NOT_NULL") -> {
if(c.origin != IrStatementOrigin.EXCLEXCL) {
logger.errorElement("Unexpected origin for CHECK_NOT_NULL: ${c.origin}", c)
logger.warnElement("Unexpected origin for CHECK_NOT_NULL: ${c.origin}", c)
}
val id = tw.getFreshIdLabel<DbNotnullexpr>()
@@ -2394,7 +2394,7 @@ open class KotlinFileExtractor(
val stmtParent = parent.stmt(e, callable)
val irConstructor = declarationStack.peek() as? IrConstructor
if (irConstructor == null) {
logger.warnElement("IrInstanceInitializerCall outside constructor", e)
logger.errorElement("IrInstanceInitializerCall outside constructor", e)
return
}
extractInstanceInitializerBlock(stmtParent, irConstructor)
@@ -3368,7 +3368,7 @@ open class KotlinFileExtractor(
) {
with("function reference", functionReferenceExpr) {
val target = functionReferenceExpr.reflectionTarget ?: run {
logger.errorElement("Expected to find reflection target for function reference. Using underlying symbol instead.", functionReferenceExpr)
logger.warnElement("Expected to find reflection target for function reference. Using underlying symbol instead.", functionReferenceExpr)
functionReferenceExpr.symbol
}

View File

@@ -1,4 +1,3 @@
isFinalField
| test.kt:3:3:3:18 | x |
#select
| test.kt:3:3:3:18 | this.x | test.kt:6:10:6:10 | getX(...) |
#select

View File

@@ -4,9 +4,7 @@ import semmle.code.java.dataflow.DataFlow
class Config extends DataFlow::Configuration {
Config() { this = "Config" }
override predicate isSource(DataFlow::Node n) {
n.asExpr().(CompileTimeConstantExpr).getStringValue() = "Source"
}
override predicate isSource(DataFlow::Node n) { n.asExpr().(StringLiteral).getValue() = "Source" }
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"

View File

@@ -27,7 +27,10 @@ py_binary(
py_binary(
name = "trapgen",
srcs = ["trapgen.py"],
data = ["//swift/codegen/templates:trap"],
data = [
"//swift:dbscheme",
"//swift/codegen/templates:trap",
],
visibility = ["//swift:__subpackages__"],
deps = [
"//swift/codegen/lib",
@@ -38,7 +41,11 @@ py_binary(
py_binary(
name = "cppgen",
srcs = ["cppgen.py"],
data = ["//swift/codegen/templates:cpp"],
data = [
":schema",
":schema_includes",
"//swift/codegen/templates:cpp",
],
visibility = ["//swift:__subpackages__"],
deps = [
"//swift/codegen/lib",

View File

@@ -12,12 +12,12 @@ _directories:
expr: Expr$
stmt: Stmt$
Element:
is_unknown: predicate
File:
name: string
IterableDeclContext:
members: Decl*
Locatable:
location: Location
@@ -32,6 +32,9 @@ Type:
diagnostics_name: string
canonical_type: Type
IterableDeclContext:
members: Decl*
ExtensionDecl:
_extends:
- GenericContext
@@ -74,6 +77,8 @@ BuiltinType:
DependentMemberType:
_extends: Type
baseType: Type
associated_type_decl: AssociatedTypeDecl
DynamicSelfType:
_extends: Type
@@ -123,14 +128,12 @@ SugarType:
TupleType:
_extends: Type
types: Type*
names: string*
TypeVariableType:
_extends: Type
UnknownType:
_extends: Type
name: string
UnresolvedType:
_extends: Type
@@ -232,12 +235,14 @@ GenericTypeParamType:
ParenType:
_extends: SugarType
type: Type
SyntaxSugarType:
_extends: SugarType
TypeAliasType:
_extends: SugarType
decl: TypeAliasDecl
EnumCaseDecl:
_extends: Decl
@@ -254,6 +259,7 @@ MissingMemberDecl:
OperatorDecl:
_extends: Decl
name: string
PatternBindingDecl:
_extends: Decl
@@ -270,15 +276,6 @@ TopLevelCodeDecl:
_extends: Decl
body: BraceStmt
UnknownAstNode:
_extends:
- Decl
- Expr
- Pattern
- Stmt
- TypeRepr
name: string
ValueDecl:
_extends: Decl
interface_type: Type
@@ -599,6 +596,7 @@ YieldStmt:
BoundGenericType:
_extends: NominalOrBoundGenericNominalType
arg_types: Type*
NominalType:
_extends: NominalOrBoundGenericNominalType
@@ -608,6 +606,7 @@ BuiltinIntegerLiteralType:
BuiltinIntegerType:
_extends: AnyBuiltinIntegerType
width: int?
NestedArchetypeType:
_extends: ArchetypeType
@@ -627,12 +626,16 @@ PrimaryArchetypeType:
DictionaryType:
_extends: SyntaxSugarType
key_type: Type
value_type: Type
UnarySyntaxSugarType:
_extends: SyntaxSugarType
base_type: Type
InfixOperatorDecl:
_extends: OperatorDecl
precedence_group: PrecedenceGroupDecl?
PostfixOperatorDecl:
_extends: OperatorDecl
@@ -659,6 +662,7 @@ EnumElementDecl:
TypeDecl:
_extends: ValueDecl
name: string
base_types: Type*
AutoClosureExpr:
_extends: AbstractClosureExpr
@@ -859,9 +863,10 @@ DoStmt:
ForEachStmt:
_extends: LabeledStmt
body: BraceStmt
pattern: Pattern
sequence: Expr
where: Expr?
body: BraceStmt
LabeledConditionalStmt:
_extends: LabeledStmt
@@ -893,7 +898,6 @@ BoundGenericStructType:
ClassType:
_extends: NominalType
decl: ClassDecl
EnumType:
_extends: NominalType
@@ -903,7 +907,6 @@ ProtocolType:
StructType:
_extends: NominalType
decl: StructDecl
ArraySliceType:
_extends: UnarySyntaxSugarType
@@ -930,6 +933,9 @@ VarDecl:
_extends: AbstractStorageDecl
name: string
type: Type
attached_property_wrapper_type: Type?
parent_pattern: Pattern?
parent_initializer: Expr?
AbstractTypeParamDecl:
_extends: TypeDecl
@@ -1026,3 +1032,87 @@ FloatLiteralExpr:
IntegerLiteralExpr:
_extends: NumberLiteralExpr
string_value: string
ErrorTypeRepr:
_extends: TypeRepr
AttributedTypeRepr:
_extends: TypeRepr
IdentTypeRepr:
_extends: TypeRepr
ComponentIdentTypeRepr:
_extends: IdentTypeRepr
SimpleIdentTypeRepr:
_extends: ComponentIdentTypeRepr
GenericIdentTypeRepr:
_extends: ComponentIdentTypeRepr
CompoundIdentTypeRepr:
_extends: IdentTypeRepr
FunctionTypeRepr:
_extends: TypeRepr
ArrayTypeRepr:
_extends: TypeRepr
DictionaryTypeRepr:
_extends: TypeRepr
OptionalTypeRepr:
_extends: TypeRepr
ImplicitlyUnwrappedOptionalTypeRepr:
_extends: TypeRepr
TupleTypeRepr:
_extends: TypeRepr
CompositionTypeRepr:
_extends: TypeRepr
MetatypeTypeRepr:
_extends: TypeRepr
ProtocolTypeRepr:
_extends: TypeRepr
OpaqueReturnTypeRepr:
_extends: TypeRepr
NamedOpaqueReturnTypeRepr:
_extends: TypeRepr
ExistentialTypeRepr:
_extends: TypeRepr
PlaceholderTypeRepr:
_extends: TypeRepr
SpecifierTypeRepr:
_extends: TypeRepr
InOutTypeRepr:
_extends: SpecifierTypeRepr
SharedTypeRepr:
_extends: SpecifierTypeRepr
OwnedTypeRepr:
_extends: SpecifierTypeRepr
IsolatedTypeRepr:
_extends: SpecifierTypeRepr
CompileTimeConstTypeRepr:
_extends: SpecifierTypeRepr
FixedTypeRepr:
_extends: TypeRepr
SilBoxTypeRepr:
_extends: TypeRepr

View File

@@ -29,5 +29,14 @@ inline std::ostream &operator<<(std::ostream &out, const {{name}}{{trap_affix}}
<< {{#get_streamer}}e.{{field_name}}{{/get_streamer}}{{/fields}} << ")";
return out;
}
{{#id}}
namespace detail {
template<>
struct ToBindingTrapFunctor<{{type}}> {
using type = {{name}}{{trap_affix}};
};
}
{{/id}}
{{/traps}}
}

View File

@@ -3,22 +3,24 @@ load("//swift:rules.bzl", "swift_cc_binary")
swift_cc_binary(
name = "extractor",
srcs = [
"SwiftDispatcher.h",
"SwiftExtractor.cpp",
"SwiftExtractor.h",
"SwiftExtractorConfiguration.h",
"SwiftDispatcher.h",
"SwiftTagTraits.h",
"main.cpp",
"SwiftVisitor.h",
"main.cpp",
"visitors/DeclVisitor.h",
"visitors/ExprVisitor.h",
"visitors/StmtVisitor.h",
"visitors/TypeVisitor.h",
"visitors/PatternVisitor.h",
"visitors/StmtVisitor.h",
"visitors/TypeReprVisitor.h",
"visitors/TypeVisitor.h",
"visitors/VisitorBase.h",
],
visibility = ["//swift:__pkg__"],
deps = [
"//swift/tools/prebuilt:swift-llvm-support",
"//swift/extractor/trap",
"//swift/tools/prebuilt:swift-llvm-support",
],
)

View File

@@ -10,42 +10,6 @@
namespace codeql {
namespace detail {
// The following `getKindName`s are used within "TBD" TRAP entries to visually mark an AST node as
// not properly emitted yet.
// TODO: To be replaced with QL counterpart
template <typename Parent, typename Kind>
inline std::string getKindName(Kind kind) {
return Parent::getKindName(kind).str();
}
template <>
inline std::string getKindName<swift::TypeBase, swift::TypeKind>(swift::TypeKind kind) {
switch (kind) {
#define TYPE(CLASS, PARENT) \
case swift::TypeKind::CLASS: \
return #CLASS;
#include "swift/AST/TypeNodes.def"
default:
return "Unknown";
}
}
template <>
std::string inline getKindName<swift::TypeRepr, swift::TypeReprKind>(swift::TypeReprKind kind) {
switch (kind) {
#define TYPEREPR(CLASS, PARENT) \
case swift::TypeReprKind::CLASS: \
return #CLASS;
#include "swift/AST/TypeReprNodes.def"
default:
return "Unknown";
}
}
} // namespace detail
// The main responsibilities of the SwiftDispatcher are as follows:
// * redirect specific AST node emission to a corresponding visitor (statements, expressions, etc.)
// * storing TRAP labels for emitted AST nodes (in the TrapLabelStore) to avoid re-emission
@@ -57,28 +21,22 @@ class SwiftDispatcher {
SwiftDispatcher(const swift::SourceManager& sourceManager, TrapArena& arena, TrapOutput& trap)
: sourceManager{sourceManager}, arena{arena}, trap{trap} {}
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
template <typename Parent, typename Child>
void TBD(Child* entity, const std::string& suffix) {
using namespace std::string_literals;
auto label = assignNewLabel(entity);
auto kind = detail::getKindName<Parent>(static_cast<const Parent*>(entity)->getKind());
auto name = "TBD ("s + kind + suffix + ")";
if constexpr (std::is_same_v<Parent, swift::TypeBase>) {
trap.emit(UnknownTypesTrap{label, name});
} else {
trap.emit(UnknownAstNodesTrap{label, name});
}
template <typename Entry>
void emit(const Entry& entry) {
trap.emit(entry);
}
private:
// types to be supported by assignNewLabel/fetchLabel need to be listed here
using Store = TrapLabelStore<swift::Decl,
swift::Stmt,
swift::Expr,
swift::Pattern,
swift::TypeRepr,
swift::TypeBase>;
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
template <typename E>
void emitUnknown(E* entity) {
auto label = assignNewLabel(entity);
using Trap = BindingTrapOf<E>;
static_assert(sizeof(Trap) == sizeof(label),
"Binding traps of unknown entities must only have the `id` field (the class "
"should be empty in schema.yml)");
emit(Trap{label});
emit(ElementIsUnknownTrap{label});
}
// 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
@@ -88,7 +46,7 @@ class SwiftDispatcher {
// this is required so we avoid any recursive loop: a `fetchLabel` during the visit of `e` might
// end up calling `fetchLabel` on `e` itself, so we want the visit of `e` to call `fetchLabel`
// only after having called `assignNewLabel` on `e`.
assert(holds_alternative<std::monostate>(waitingForNewLabel) &&
assert(std::holds_alternative<std::monostate>(waitingForNewLabel) &&
"fetchLabel called before assignNewLabel");
if (auto l = store.get(e)) {
return *l;
@@ -105,22 +63,38 @@ class SwiftDispatcher {
return {};
}
// convenience `fetchLabel` overload for `swift::Type` (which is just a wrapper for
// `swift::TypeBase*`)
TrapLabel<TypeTag> fetchLabel(swift::Type t) { return fetchLabel(t.getPointer()); }
TrapLabel<AstNodeTag> fetchLabel(swift::ASTNode node) {
return fetchLabelFromUnion<AstNodeTag>(node);
}
// Due to the lazy emission approach, we must assign a label to a corresponding AST node before
// it actually gets emitted to handle recursive cases such as recursive calls, or recursive type
// declarations
template <typename E>
TrapLabelOf<E> assignNewLabel(E* e) {
assert(waitingForNewLabel == Store::Handle{e} && "assignNewLabel called on wrong entity");
auto label = getLabel<TrapTagOf<E>>();
trap.assignStar(label);
auto label = createLabel<TrapTagOf<E>>();
store.insert(e, label);
waitingForNewLabel = std::monostate{};
return label;
}
template <typename Tag>
TrapLabel<Tag> getLabel() {
return arena.allocateLabel<Tag>();
TrapLabel<Tag> createLabel() {
auto ret = arena.allocateLabel<Tag>();
trap.assignStar(ret);
return ret;
}
template <typename Tag, typename... Args>
TrapLabel<Tag> createLabel(Args&&... args) {
auto ret = arena.allocateLabel<Tag>();
trap.assignKey(ret, std::forward<Args>(args)...);
return ret;
}
template <typename Locatable>
@@ -128,29 +102,70 @@ class SwiftDispatcher {
attachLocation(&locatable, locatableLabel);
}
// Emits a Location TRAP entry and attaches it to an AST node
// Emits a Location TRAP entry and attaches it to a `Locatable` trap label
template <typename Locatable>
void attachLocation(Locatable* locatable, TrapLabel<LocatableTag> locatableLabel) {
auto start = locatable->getStartLoc();
auto end = locatable->getEndLoc();
attachLocation(locatable->getStartLoc(), locatable->getEndLoc(), locatableLabel);
}
// Emits a Location TRAP entry for a list of swift entities and attaches it to a `Locatable` trap
// label
template <typename Locatable>
void attachLocation(llvm::MutableArrayRef<Locatable>* locatables,
TrapLabel<LocatableTag> locatableLabel) {
if (locatables->empty()) {
return;
}
attachLocation(locatables->front().getStartLoc(), locatables->back().getEndLoc(),
locatableLabel);
}
private:
// types to be supported by assignNewLabel/fetchLabel need to be listed here
using Store = TrapLabelStore<swift::Decl,
swift::Stmt,
swift::StmtCondition,
swift::CaseLabelItem,
swift::Expr,
swift::Pattern,
swift::TypeRepr,
swift::TypeBase>;
void attachLocation(swift::SourceLoc start,
swift::SourceLoc end,
TrapLabel<LocatableTag> locatableLabel) {
if (!start.isValid() || !end.isValid()) {
// invalid locations seem to come from entities synthesized by the compiler
return;
}
std::string filepath = getFilepath(start);
auto fileLabel = arena.allocateLabel<FileTag>();
trap.assignKey(fileLabel, filepath);
auto fileLabel = createLabel<FileTag>(filepath);
// TODO: do not emit duplicate trap entries for Files
trap.emit(FilesTrap{fileLabel, filepath});
auto [startLine, startColumn] = sourceManager.getLineAndColumnInBuffer(start);
auto [endLine, endColumn] = sourceManager.getLineAndColumnInBuffer(end);
auto locLabel = arena.allocateLabel<LocationTag>();
trap.assignKey(locLabel, '{', fileLabel, "}:", startLine, ':', startColumn, ':', endLine, ':',
endColumn);
auto locLabel = createLabel<LocationTag>('{', fileLabel, "}:", startLine, ':', startColumn, ':',
endLine, ':', endColumn);
trap.emit(LocationsTrap{locLabel, fileLabel, startLine, startColumn, endLine, endColumn});
trap.emit(LocatablesTrap{locatableLabel, locLabel});
}
template <typename Tag, typename... Ts>
TrapLabel<Tag> fetchLabelFromUnion(const llvm::PointerUnion<Ts...> u) {
TrapLabel<Tag> ret{};
assert((... || fetchLabelFromUnionCase<Tag, Ts>(u, ret)) && "llvm::PointerUnion not set");
return ret;
}
template <typename Tag, typename T, typename... Ts>
bool fetchLabelFromUnionCase(const llvm::PointerUnion<Ts...> u, TrapLabel<Tag>& output) {
if (auto e = u.template dyn_cast<T>()) {
output = fetchLabel(e);
return true;
}
return false;
}
std::string getFilepath(swift::SourceLoc loc) {
// TODO: this needs more testing
// TODO: check canonicaliztion of names on a case insensitive filesystems
@@ -168,6 +183,8 @@ class SwiftDispatcher {
// which are to be introduced in follow-up PRs
virtual void visit(swift::Decl* decl) = 0;
virtual void visit(swift::Stmt* stmt) = 0;
virtual void visit(swift::StmtCondition* cond) = 0;
virtual void visit(swift::CaseLabelItem* item) = 0;
virtual void visit(swift::Expr* expr) = 0;
virtual void visit(swift::Pattern* pattern) = 0;
virtual void visit(swift::TypeRepr* type) = 0;

View File

@@ -14,6 +14,7 @@ using SILBlockStorageTypeTag = SilBlockStorageTypeTag;
using SILBoxTypeTag = SilBoxTypeTag;
using SILFunctionTypeTag = SilFunctionTypeTag;
using SILTokenTypeTag = SilTokenTypeTag;
using SILBoxTypeReprTag = SilBoxTypeReprTag;
#define MAP_TYPE_TO_TAG(TYPE, TAG) \
template <> \
@@ -34,6 +35,8 @@ using SILTokenTypeTag = SilTokenTypeTag;
static_assert(std::is_base_of_v<TYPE##Tag, TAG>, "override is not a subtag");
MAP_TAG(Stmt);
MAP_TAG(StmtCondition);
MAP_TAG(CaseLabelItem);
#define ABSTRACT_STMT(CLASS, PARENT) MAP_SUBTAG(CLASS##Stmt, PARENT)
#define STMT(CLASS, PARENT) ABSTRACT_STMT(CLASS, PARENT)
#include "swift/AST/StmtNodes.def"
@@ -54,6 +57,10 @@ MAP_TAG(Pattern);
#include "swift/AST/PatternNodes.def"
MAP_TAG(TypeRepr);
#define ABSTRACT_TYPEREPR(CLASS, PARENT) MAP_SUBTAG(CLASS##TypeRepr, PARENT)
#define TYPEREPR(CLASS, PARENT) ABSTRACT_TYPEREPR(CLASS, PARENT)
#include "swift/AST/TypeReprNodes.def"
MAP_TYPE_TO_TAG(TypeBase, TypeTag);
#define ABSTRACT_TYPE(CLASS, PARENT) MAP_SUBTAG(CLASS##Type, PARENT)
#define TYPE(CLASS, PARENT) ABSTRACT_TYPE(CLASS, PARENT)

View File

@@ -5,6 +5,7 @@
#include "swift/extractor/visitors/ExprVisitor.h"
#include "swift/extractor/visitors/StmtVisitor.h"
#include "swift/extractor/visitors/TypeVisitor.h"
#include "swift/extractor/visitors/TypeReprVisitor.h"
#include "swift/extractor/visitors/PatternVisitor.h"
namespace codeql {
@@ -21,14 +22,17 @@ class SwiftVisitor : private SwiftDispatcher {
private:
void visit(swift::Decl* decl) override { declVisitor.visit(decl); }
void visit(swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
void visit(swift::StmtCondition* cond) override { stmtVisitor.visitStmtCondition(cond); }
void visit(swift::CaseLabelItem* item) override { stmtVisitor.visitCaseLabelItem(item); }
void visit(swift::Expr* expr) override { exprVisitor.visit(expr); }
void visit(swift::Pattern* pattern) override { patternVisitor.visit(pattern); }
void visit(swift::TypeRepr* type) override { TBD<swift::TypeRepr>(type, "TypeRepr"); }
void visit(swift::TypeRepr* type) override { typeReprVisitor.visit(type); }
void visit(swift::TypeBase* type) override { typeVisitor.visit(type); }
DeclVisitor declVisitor{*this};
ExprVisitor exprVisitor{*this};
StmtVisitor stmtVisitor{*this};
TypeReprVisitor typeReprVisitor{*this};
TypeVisitor typeVisitor{*this};
PatternVisitor patternVisitor{*this};
};

View File

@@ -4,8 +4,6 @@
#include <iostream>
#include <string>
#include "swift/extractor/trap/generated/TrapTags.h"
namespace codeql {
class UntypedTrapLabel {
@@ -15,12 +13,18 @@ class UntypedTrapLabel {
template <typename Tag>
friend class TrapLabel;
static constexpr uint64_t undefined = 0xffffffffffffffff;
protected:
UntypedTrapLabel() : id_{0xffffffffffffffff} {}
UntypedTrapLabel() : id_{undefined} {}
UntypedTrapLabel(uint64_t id) : id_{id} {}
public:
friend std::ostream& operator<<(std::ostream& out, UntypedTrapLabel l) {
// TODO: this is a temporary fix to catch us from outputting undefined labels to trap
// this should be moved to a validity check, probably aided by code generation and carried out
// by `SwiftDispatcher`
assert(l.id_ != undefined && "outputting an undefined label!");
out << '#' << std::hex << l.id_ << std::dec;
return out;
}
@@ -46,14 +50,7 @@ class TrapLabel : public UntypedTrapLabel {
template <typename OtherTag>
TrapLabel(const TrapLabel<OtherTag>& other) : UntypedTrapLabel(other) {
// we temporarily need to bypass the label type system for unknown AST nodes and types
if constexpr (std::is_same_v<Tag, UnknownAstNodeTag>) {
static_assert(std::is_base_of_v<AstNodeTag, OtherTag>, "wrong label assignment!");
} else if constexpr (std::is_same_v<Tag, UnknownTypeTag>) {
static_assert(std::is_base_of_v<TypeTag, OtherTag>, "wrong label assignment!");
} else {
static_assert(std::is_base_of_v<Tag, OtherTag>, "wrong label assignment!");
}
static_assert(std::is_base_of_v<Tag, OtherTag>, "wrong label assignment!");
}
};

View File

@@ -8,11 +8,17 @@
namespace codeql {
namespace detail {
// must be instantiated for default mapping from entities to tags
template <typename T>
struct ToTagFunctor;
// can be instantiated to override the default mapping for special cases
template <typename T>
struct ToTagOverride : ToTagFunctor<T> {};
// must be instantiated to map trap labels to the corresponding generated binding trap entry
template <typename Label>
struct ToBindingTrapFunctor;
} // namespace detail
template <typename T>
@@ -21,4 +27,7 @@ using TrapTagOf = typename detail::ToTagOverride<std::remove_const_t<T>>::type;
template <typename T>
using TrapLabelOf = TrapLabel<TrapTagOf<T>>;
template <typename T>
using BindingTrapOf = typename detail::ToBindingTrapFunctor<TrapLabelOf<T>>::type;
} // namespace codeql

View File

@@ -1,22 +1,256 @@
#pragma once
#include "swift/extractor/SwiftDispatcher.h"
#include <swift/AST/ASTVisitor.h>
#include <swift/AST/Decl.h>
#include <swift/AST/GenericParamList.h>
#include <swift/AST/ParameterList.h>
#include "swift/extractor/visitors/VisitorBase.h"
namespace codeql {
class DeclVisitor : public swift::DeclVisitor<DeclVisitor> {
// `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:
// SwiftDispatcher should outlive the DeclVisitor
DeclVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
using AstVisitorBase<DeclVisitor>::AstVisitorBase;
template <typename E>
void visitDecl(E* decl) {
dispatcher.TBD<swift::Decl>(decl, "Decl");
void visitFuncDecl(swift::FuncDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ConcreteFuncDeclsTrap{label});
emitAbstractFunctionDecl(decl, label);
}
void visitConstructorDecl(swift::ConstructorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ConstructorDeclsTrap{label});
emitConstructorDecl(decl, label);
}
void visitDestructorDecl(swift::DestructorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(DestructorDeclsTrap{label});
emitDestructorDecl(decl, label);
}
void visitPrefixOperatorDecl(swift::PrefixOperatorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PrefixOperatorDeclsTrap{label});
emitOperatorDecl(decl, label);
}
void visitPostfixOperatorDecl(swift::PostfixOperatorDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PostfixOperatorDeclsTrap{label});
emitOperatorDecl(decl, label);
}
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 visitPrecedenceGroupDecl(swift::PrecedenceGroupDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PrecedenceGroupDeclsTrap{label});
}
void visitParamDecl(swift::ParamDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ParamDeclsTrap{label});
emitVarDecl(decl, label);
}
void visitTopLevelCodeDecl(swift::TopLevelCodeDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
assert(decl->getBody() && "Expect top level code to have body");
dispatcher_.emit(TopLevelCodeDeclsTrap{label, dispatcher_.fetchLabel(decl->getBody())});
}
void visitPatternBindingDecl(swift::PatternBindingDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(PatternBindingDeclsTrap{label});
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)});
}
}
}
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 visitStructDecl(swift::StructDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(StructDeclsTrap{label});
emitNominalTypeDecl(decl, label);
}
void visitClassDecl(swift::ClassDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ClassDeclsTrap{label});
emitNominalTypeDecl(decl, label);
}
void visitEnumDecl(swift::EnumDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(EnumDeclsTrap{label});
emitNominalTypeDecl(decl, label);
}
void visitProtocolDecl(swift::ProtocolDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(ProtocolDeclsTrap{label});
emitNominalTypeDecl(decl, label);
}
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 visitEnumElementDecl(swift::EnumElementDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(EnumElementDeclsTrap{label, decl->getNameStr().str()});
if (decl->hasParameterList()) {
auto i = 0u;
for (auto p : *decl->getParameterList()) {
dispatcher_.emit(EnumElementDeclParamsTrap{label, i++, dispatcher_.fetchLabel(p)});
}
}
}
void visitGenericTypeParamDecl(swift::GenericTypeParamDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(GenericTypeParamDeclsTrap{label});
emitTypeDecl(decl, label);
}
void visitAssociatedTypeDecl(swift::AssociatedTypeDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(AssociatedTypeDeclsTrap{label});
emitTypeDecl(decl, label);
}
void visitTypeAliasDecl(swift::TypeAliasDecl* decl) {
auto label = dispatcher_.assignNewLabel(decl);
dispatcher_.emit(TypeAliasDeclsTrap{label});
emitTypeDecl(decl, label);
}
private:
SwiftDispatcher& dispatcher;
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) {
assert(decl->hasName() && "Expect functions to have name");
assert(decl->hasParameterList() && "Expect functions to have a parameter list");
auto name = 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);
}
void emitOperatorDecl(swift::OperatorDecl* decl, TrapLabel<OperatorDeclTag> label) {
dispatcher_.emit(OperatorDeclsTrap{label, decl->getName().str().str()});
}
void emitTypeDecl(swift::TypeDecl* decl, TrapLabel<TypeDeclTag> label) {
dispatcher_.emit(TypeDeclsTrap{label, decl->getNameStr().str()});
auto i = 0u;
for (auto& typeLoc : decl->getInherited()) {
auto type = typeLoc.getType();
if (type.isNull()) {
continue;
}
dispatcher_.emit(TypeDeclBaseTypesTrap{label, i++, dispatcher_.fetchLabel(type)});
}
emitValueDecl(decl, label);
}
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 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)});
}
if (decl->hasAttachedPropertyWrapper()) {
if (auto propertyType = decl->getPropertyWrapperBackingPropertyType();
!propertyType.isNull()) {
dispatcher_.emit(
VarDeclAttachedPropertyWrapperTypesTrap{label, dispatcher_.fetchLabel(propertyType)});
}
}
emitValueDecl(decl, label);
}
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 emitGenericContext(const swift::GenericContext* decl, TrapLabel<GenericContextTag> label) {
if (auto params = decl->getGenericParams()) {
auto i = 0u;
for (auto t : *params) {
dispatcher_.emit(
GenericContextGenericTypeParamsTrap{label, i++, dispatcher_.fetchLabel(t)});
}
}
}
void emitValueDecl(const swift::ValueDecl* decl, TrapLabel<ValueDeclTag> label) {
assert(decl->getInterfaceType() && "Expect ValueDecl to have InterfaceType");
dispatcher_.emit(ValueDeclsTrap{label, dispatcher_.fetchLabel(decl->getInterfaceType())});
}
};
} // namespace codeql

View File

@@ -1,22 +1,547 @@
#pragma once
#include "swift/extractor/SwiftDispatcher.h"
#include <swift/AST/ASTVisitor.h>
#include "swift/extractor/visitors/VisitorBase.h"
namespace codeql {
class ExprVisitor : public swift::ExprVisitor<ExprVisitor> {
class ExprVisitor : public AstVisitorBase<ExprVisitor> {
public:
// SwiftDispatcher should outlive the ExprVisitor
ExprVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
using AstVisitorBase<ExprVisitor>::AstVisitorBase;
template <typename E>
void visitExpr(E* expr) {
dispatcher.TBD<swift::Expr>(expr, "Expr");
void visit(swift::Expr* expr) {
swift::ExprVisitor<ExprVisitor, void>::visit(expr);
auto label = dispatcher_.fetchLabel(expr);
if (auto type = expr->getType()) {
dispatcher_.emit(ExprTypesTrap{label, dispatcher_.fetchLabel(type)});
}
}
void visitIntegerLiteralExpr(swift::IntegerLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
auto value = (expr->isNegative() ? "-" : "") + expr->getDigitsText().str();
dispatcher_.emit(IntegerLiteralExprsTrap{label, value});
}
void visitFloatLiteralExpr(swift::FloatLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
auto value = (expr->isNegative() ? "-" : "") + expr->getDigitsText().str();
dispatcher_.emit(FloatLiteralExprsTrap{label, value});
}
void visitBooleanLiteralExpr(swift::BooleanLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(BooleanLiteralExprsTrap{label, expr->getValue()});
}
void visitMagicIdentifierLiteralExpr(swift::MagicIdentifierLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
auto kind = swift::MagicIdentifierLiteralExpr::getKindString(expr->getKind()).str();
dispatcher_.emit(MagicIdentifierLiteralExprsTrap{label, kind});
}
void visitStringLiteralExpr(swift::StringLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(StringLiteralExprsTrap{label, expr->getValue().str()});
}
void visitInterpolatedStringLiteralExpr(swift::InterpolatedStringLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(InterpolatedStringLiteralExprsTrap{label});
if (auto interpolation = expr->getInterpolationExpr()) {
auto ref = dispatcher_.fetchLabel(interpolation);
dispatcher_.emit(InterpolatedStringLiteralExprInterpolationExprsTrap{label, ref});
}
if (auto count = expr->getInterpolationCountExpr()) {
auto ref = dispatcher_.fetchLabel(count);
dispatcher_.emit(InterpolatedStringLiteralExprInterpolationCountExprsTrap{label, ref});
}
if (auto capacity = expr->getLiteralCapacityExpr()) {
auto ref = dispatcher_.fetchLabel(capacity);
dispatcher_.emit(InterpolatedStringLiteralExprLiteralCapacityExprsTrap{label, ref});
}
if (auto appending = expr->getAppendingExpr()) {
auto ref = dispatcher_.fetchLabel(appending);
dispatcher_.emit(InterpolatedStringLiteralExprAppendingExprsTrap{label, ref});
}
}
void visitNilLiteralExpr(swift::NilLiteralExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(NilLiteralExprsTrap{label});
}
void visitCallExpr(swift::CallExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(CallExprsTrap{label});
emitApplyExpr(expr, label);
}
void visitPrefixUnaryExpr(swift::PrefixUnaryExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(PrefixUnaryExprsTrap{label});
emitApplyExpr(expr, label);
}
void visitDeclRefExpr(swift::DeclRefExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(DeclRefExprsTrap{label, dispatcher_.fetchLabel(expr->getDecl())});
auto i = 0u;
for (auto t : expr->getDeclRef().getSubstitutions().getReplacementTypes()) {
dispatcher_.emit(DeclRefExprReplacementTypesTrap{label, i++, dispatcher_.fetchLabel(t)});
}
}
void visitAssignExpr(swift::AssignExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getDest() && "AssignExpr has Dest");
assert(expr->getSrc() && "AssignExpr has Src");
auto dest = dispatcher_.fetchLabel(expr->getDest());
auto src = dispatcher_.fetchLabel(expr->getSrc());
dispatcher_.emit(AssignExprsTrap{label, dest, src});
}
void visitBindOptionalExpr(swift::BindOptionalExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "BindOptionalExpr has SubExpr");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(BindOptionalExprsTrap{label, subExpr});
}
void visitCaptureListExpr(swift::CaptureListExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getClosureBody() && "CaptureListExpr has ClosureBody");
auto closureBody = dispatcher_.fetchLabel(expr->getClosureBody());
dispatcher_.emit(CaptureListExprsTrap{label, closureBody});
unsigned index = 0;
for (auto& entry : expr->getCaptureList()) {
auto captureLabel = dispatcher_.fetchLabel(entry.PBD);
dispatcher_.emit(CaptureListExprBindingDeclsTrap{label, index++, captureLabel});
}
}
void visitBinaryExpr(swift::BinaryExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(BinaryExprsTrap{label});
emitApplyExpr(expr, label);
}
void visitTupleExpr(swift::TupleExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(TupleExprsTrap{label});
unsigned index = 0;
for (auto element : expr->getElements()) {
auto elementLabel = dispatcher_.fetchLabel(element);
dispatcher_.emit(TupleExprElementsTrap{label, index++, elementLabel});
}
}
void visitDefaultArgumentExpr(swift::DefaultArgumentExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getParamDecl() && "DefaultArgumentExpr has getParamDecl");
/// TODO: suddenly, getParamDecl is const, monkey-patching it here
auto paramLabel = dispatcher_.fetchLabel((swift::ParamDecl*)expr->getParamDecl());
dispatcher_.emit(
DefaultArgumentExprsTrap{label, paramLabel, static_cast<int>(expr->getParamIndex())});
if (expr->isCallerSide()) {
auto callSiteDefaultLabel = dispatcher_.fetchLabel(expr->getCallerSideDefaultExpr());
dispatcher_.emit(DefaultArgumentExprCallerSideDefaultsTrap{label, callSiteDefaultLabel});
}
}
void visitDotSyntaxBaseIgnoredExpr(swift::DotSyntaxBaseIgnoredExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getLHS() && "DotSyntaxBaseIgnoredExpr has LHS");
assert(expr->getRHS() && "DotSyntaxBaseIgnoredExpr has RHS");
auto lhs = dispatcher_.fetchLabel(expr->getLHS());
auto rhs = dispatcher_.fetchLabel(expr->getRHS());
dispatcher_.emit(DotSyntaxBaseIgnoredExprsTrap{label, lhs, rhs});
}
void visitDynamicTypeExpr(swift::DynamicTypeExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBase() && "DynamicTypeExpr has Base");
auto base = dispatcher_.fetchLabel(expr->getBase());
dispatcher_.emit(DynamicTypeExprsTrap{label, base});
}
void visitEnumIsCaseExpr(swift::EnumIsCaseExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "EnumIsCaseExpr has SubExpr");
assert(expr->getCaseTypeRepr() && "EnumIsCaseExpr has CaseTypeRepr");
assert(expr->getEnumElement() && "EnumIsCaseExpr has EnumElement");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
auto typeRepr = dispatcher_.fetchLabel(expr->getCaseTypeRepr());
auto enumElement = dispatcher_.fetchLabel(expr->getEnumElement());
dispatcher_.emit(EnumIsCaseExprsTrap{label, subExpr, typeRepr, enumElement});
}
void visitMakeTemporarilyEscapableExpr(swift::MakeTemporarilyEscapableExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getOpaqueValue() && "MakeTemporarilyEscapableExpr has OpaqueValue");
assert(expr->getNonescapingClosureValue() &&
"MakeTemporarilyEscapableExpr has NonescapingClosureValue");
assert(expr->getSubExpr() && "MakeTemporarilyEscapableExpr has SubExpr");
auto opaqueValue = dispatcher_.fetchLabel(expr->getOpaqueValue());
auto nonescapingClosureValue = dispatcher_.fetchLabel(expr->getNonescapingClosureValue());
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(
MakeTemporarilyEscapableExprsTrap{label, opaqueValue, nonescapingClosureValue, subExpr});
}
void visitObjCSelectorExpr(swift::ObjCSelectorExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "ObjCSelectorExpr has SubExpr");
assert(expr->getMethod() && "ObjCSelectorExpr has Method");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
auto method = dispatcher_.fetchLabel(expr->getMethod());
dispatcher_.emit(ObjCSelectorExprsTrap{label, subExpr, method});
}
void visitOneWayExpr(swift::OneWayExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "OneWayExpr has SubExpr");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(OneWayExprsTrap{label, subExpr});
}
void visitOpenExistentialExpr(swift::OpenExistentialExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "OpenExistentialExpr has SubExpr");
assert(expr->getExistentialValue() && "OpenExistentialExpr has ExistentialValue");
assert(expr->getOpaqueValue() && "OpenExistentialExpr has OpaqueValue");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
auto existentialValue = dispatcher_.fetchLabel(expr->getExistentialValue());
auto opaqueValue = dispatcher_.fetchLabel(expr->getOpaqueValue());
dispatcher_.emit(OpenExistentialExprsTrap{label, subExpr, existentialValue, opaqueValue});
}
void visitOptionalEvaluationExpr(swift::OptionalEvaluationExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "OptionalEvaluationExpr has SubExpr");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(OptionalEvaluationExprsTrap{label, subExpr});
}
void visitRebindSelfInConstructorExpr(swift::RebindSelfInConstructorExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "RebindSelfInConstructorExpr has SubExpr");
assert(expr->getSelf() && "RebindSelfInConstructorExpr has Self");
auto subExpr = dispatcher_.fetchLabel(expr->getSubExpr());
auto self = dispatcher_.fetchLabel(expr->getSelf());
dispatcher_.emit(RebindSelfInConstructorExprsTrap{label, subExpr, self});
}
void visitSuperRefExpr(swift::SuperRefExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSelf() && "SuperRefExpr has Self");
auto self = dispatcher_.fetchLabel(expr->getSelf());
dispatcher_.emit(SuperRefExprsTrap{label, self});
}
void visitDotSyntaxCallExpr(swift::DotSyntaxCallExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(DotSyntaxCallExprsTrap{label});
emitSelfApplyExpr(expr, label);
}
void visitVarargExpansionExpr(swift::VarargExpansionExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "VarargExpansionExpr has getSubExpr()");
auto subExprLabel = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(VarargExpansionExprsTrap{label, subExprLabel});
}
void visitArrayExpr(swift::ArrayExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ArrayExprsTrap{label});
unsigned index = 0;
for (auto element : expr->getElements()) {
auto elementLabel = dispatcher_.fetchLabel(element);
dispatcher_.emit(ArrayExprElementsTrap{label, index++, elementLabel});
}
}
void visitErasureExpr(swift::ErasureExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ErasureExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitTypeExpr(swift::TypeExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(TypeExprsTrap{label});
if (auto repr = expr->getTypeRepr()) {
auto typeLabel = dispatcher_.fetchLabel(repr);
dispatcher_.emit(TypeExprTypeReprsTrap{label, typeLabel});
}
}
void visitParenExpr(swift::ParenExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ParenExprsTrap{label});
emitIdentityExpr(expr, label);
}
void visitLoadExpr(swift::LoadExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(LoadExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitInOutExpr(swift::InOutExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "InOutExpr has getSubExpr()");
auto subExprLabel = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(InOutExprsTrap{label, subExprLabel});
}
void visitOpaqueValueExpr(swift::OpaqueValueExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(OpaqueValueExprsTrap{label});
}
void visitTapExpr(swift::TapExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getVar() && "TapExpr has getVar()");
assert(expr->getBody() && "TapExpr has getBody()");
auto varLabel = dispatcher_.fetchLabel(expr->getVar());
auto bodyLabel = dispatcher_.fetchLabel(expr->getBody());
dispatcher_.emit(TapExprsTrap{label, varLabel, bodyLabel});
if (auto subExpr = expr->getSubExpr()) {
dispatcher_.emit(TapExprSubExprsTrap{label, dispatcher_.fetchLabel(subExpr)});
}
}
void visitTupleElementExpr(swift::TupleElementExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBase() && "TupleElementExpr has getBase()");
auto base = dispatcher_.fetchLabel(expr->getBase());
auto index = expr->getFieldNumber();
dispatcher_.emit(TupleElementExprsTrap{label, base, index});
}
void visitTryExpr(swift::TryExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(TryExprsTrap{label});
emitAnyTryExpr(expr, label);
}
void visitForceTryExpr(swift::ForceTryExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ForceTryExprsTrap{label});
emitAnyTryExpr(expr, label);
}
void visitOptionalTryExpr(swift::OptionalTryExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(OptionalTryExprsTrap{label});
emitAnyTryExpr(expr, label);
}
void visitInjectIntoOptionalExpr(swift::InjectIntoOptionalExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(InjectIntoOptionalExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitConstructorRefCallExpr(swift::ConstructorRefCallExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ConstructorRefCallExprsTrap{label});
emitSelfApplyExpr(expr, label);
}
void visitDiscardAssignmentExpr(swift::DiscardAssignmentExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(DiscardAssignmentExprsTrap{label});
}
void visitClosureExpr(swift::ClosureExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBody() && "ClosureExpr has getBody()");
auto bodyLabel = dispatcher_.fetchLabel(expr->getBody());
dispatcher_.emit(ClosureExprsTrap{label, bodyLabel});
}
void visitAutoClosureExpr(swift::AutoClosureExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBody() && "AutoClosureExpr has getBody()");
auto bodyLabel = dispatcher_.fetchLabel(expr->getBody());
dispatcher_.emit(AutoClosureExprsTrap{label, bodyLabel});
}
void visitCoerceExpr(swift::CoerceExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(CoerceExprsTrap{label});
emitExplicitCastExpr(expr, label);
}
void visitConditionalCheckedCastExpr(swift::ConditionalCheckedCastExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ConditionalCheckedCastExprsTrap{label});
emitExplicitCastExpr(expr, label);
}
void visitForcedCheckedCastExpr(swift::ForcedCheckedCastExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ForcedCheckedCastExprsTrap{label});
emitExplicitCastExpr(expr, label);
}
void visitIsExpr(swift::IsExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(IsExprsTrap{label});
emitExplicitCastExpr(expr, label);
}
void visitSubscriptExpr(swift::SubscriptExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBase() && "SubscriptExpr has getBase()");
auto baseLabel = dispatcher_.fetchLabel(expr->getBase());
dispatcher_.emit(SubscriptExprsTrap{label, baseLabel});
auto i = 0u;
for (const auto& arg : *expr->getArgs()) {
dispatcher_.emit(SubscriptExprArgumentsTrap{label, i++, emitArgument(arg)});
}
}
void visitDictionaryExpr(swift::DictionaryExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(DictionaryExprsTrap{label});
unsigned index = 0;
for (auto element : expr->getElements()) {
auto elementLabel = dispatcher_.fetchLabel(element);
dispatcher_.emit(DictionaryExprElementsTrap{label, index++, elementLabel});
}
}
void visitFunctionConversionExpr(swift::FunctionConversionExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(FunctionConversionExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitInOutToPointerExpr(swift::InOutToPointerExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(InOutToPointerExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitMemberRefExpr(swift::MemberRefExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getBase() && "MemberRefExpr has getBase()");
auto baseLabel = dispatcher_.fetchLabel(expr->getBase());
dispatcher_.emit(MemberRefExprsTrap{label, baseLabel});
}
void visitDerivedToBaseExpr(swift::DerivedToBaseExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(DerivedToBaseExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitKeyPathExpr(swift::KeyPathExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(KeyPathExprsTrap{label});
if (!expr->isObjC()) {
if (auto path = expr->getParsedPath()) {
auto pathLabel = dispatcher_.fetchLabel(path);
dispatcher_.emit(KeyPathExprParsedPathsTrap{label, pathLabel});
}
if (auto root = expr->getParsedPath()) {
auto rootLabel = dispatcher_.fetchLabel(root);
dispatcher_.emit(KeyPathExprParsedRootsTrap{label, rootLabel});
}
}
}
void visitLazyInitializerExpr(swift::LazyInitializerExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "LazyInitializerExpr has getSubExpr()");
auto subExprLabel = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(LazyInitializerExprsTrap{label, subExprLabel});
}
void visitForceValueExpr(swift::ForceValueExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getSubExpr() && "ForceValueExpr has getSubExpr()");
auto subExprLabel = dispatcher_.fetchLabel(expr->getSubExpr());
dispatcher_.emit(ForceValueExprsTrap{label, subExprLabel});
}
void visitPointerToPointerExpr(swift::PointerToPointerExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(PointerToPointerExprsTrap{label});
emitImplicitConversionExpr(expr, label);
}
void visitIfExpr(swift::IfExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
assert(expr->getCondExpr() && "IfExpr has getCond()");
assert(expr->getThenExpr() && "IfExpr has getThenExpr()");
assert(expr->getElseExpr() && "IfExpr has getElseExpr()");
auto condLabel = dispatcher_.fetchLabel(expr->getCondExpr());
auto thenLabel = dispatcher_.fetchLabel(expr->getThenExpr());
auto elseLabel = dispatcher_.fetchLabel(expr->getElseExpr());
dispatcher_.emit(IfExprsTrap{label, condLabel, thenLabel, elseLabel});
}
private:
SwiftDispatcher& dispatcher;
TrapLabel<ArgumentTag> emitArgument(const swift::Argument& arg) {
auto argLabel = dispatcher_.createLabel<ArgumentTag>();
assert(arg.getExpr() && "Argument has getExpr");
dispatcher_.emit(
ArgumentsTrap{argLabel, arg.getLabel().str().str(), dispatcher_.fetchLabel(arg.getExpr())});
return argLabel;
}
void emitImplicitConversionExpr(swift::ImplicitConversionExpr* expr,
TrapLabel<ImplicitConversionExprTag> label) {
assert(expr->getSubExpr() && "ImplicitConversionExpr has getSubExpr()");
dispatcher_.emit(
ImplicitConversionExprsTrap{label, dispatcher_.fetchLabel(expr->getSubExpr())});
}
void emitExplicitCastExpr(swift::ExplicitCastExpr* expr, TrapLabel<ExplicitCastExprTag> label) {
assert(expr->getSubExpr() && "ExplicitCastExpr has getSubExpr()");
dispatcher_.emit(ExplicitCastExprsTrap{label, dispatcher_.fetchLabel(expr->getSubExpr())});
}
void emitIdentityExpr(swift::IdentityExpr* expr, TrapLabel<IdentityExprTag> label) {
assert(expr->getSubExpr() && "IdentityExpr has getSubExpr()");
dispatcher_.emit(IdentityExprsTrap{label, dispatcher_.fetchLabel(expr->getSubExpr())});
}
void emitAnyTryExpr(swift::AnyTryExpr* expr, TrapLabel<AnyTryExprTag> label) {
assert(expr->getSubExpr() && "AnyTryExpr has getSubExpr()");
dispatcher_.emit(AnyTryExprsTrap{label, dispatcher_.fetchLabel(expr->getSubExpr())});
}
void emitApplyExpr(const swift::ApplyExpr* expr, TrapLabel<ApplyExprTag> label) {
assert(expr->getFn() && "CallExpr has Fn");
auto fnLabel = dispatcher_.fetchLabel(expr->getFn());
dispatcher_.emit(ApplyExprsTrap{label, fnLabel});
auto i = 0u;
for (const auto& arg : *expr->getArgs()) {
dispatcher_.emit(ApplyExprArgumentsTrap{label, i++, emitArgument(arg)});
}
}
void emitSelfApplyExpr(const swift::SelfApplyExpr* expr, TrapLabel<SelfApplyExprTag> label) {
assert(expr->getBase() && "SelfApplyExpr has getBase()");
auto baseLabel = dispatcher_.fetchLabel(expr->getBase());
dispatcher_.emit(SelfApplyExprsTrap{label, baseLabel});
emitApplyExpr(expr, label);
}
};
} // namespace codeql

View File

@@ -1,38 +1,97 @@
#pragma once
#include "swift/extractor/SwiftDispatcher.h"
#include <swift/AST/ASTVisitor.h>
#include "swift/extractor/visitors/VisitorBase.h"
namespace codeql {
namespace detail {
// swift code lacks default implementations of visitor for some entities. We can add those here
// while we do not have yet all implemented. This is a simplified version of the corresponding Expr
// code in swift/AST/ASTVisitor.h
template <typename CrtpSubclass>
class PatchedPatternVisitor : public swift::PatternVisitor<CrtpSubclass> {
class PatternVisitor : public AstVisitorBase<PatternVisitor> {
public:
#define PATTERN(CLASS, PARENT) \
void visit##CLASS##Pattern(swift::CLASS##Pattern* E) { \
return static_cast<CrtpSubclass*>(this)->visit##PARENT(E); \
}
#include "swift/AST/PatternNodes.def"
};
using AstVisitorBase<PatternVisitor>::AstVisitorBase;
} // namespace detail
class PatternVisitor : public detail::PatchedPatternVisitor<PatternVisitor> {
public:
// SwiftDispatcher should outlive the PatternVisitor
PatternVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
template <typename E>
void visitPattern(E* pattern) {
dispatcher.TBD<swift::Pattern>(pattern, "Pattern");
void visitNamedPattern(swift::NamedPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
// TODO: in some (but not all) cases, this seems to introduce a duplicate entry
// for example the vars listed in a case stmt have a different pointer than then ones in
// patterns.
// assert(pattern->getDecl() && "expect NamedPattern to have Decl");
// dispatcher_.emit(NamedPatternsTrap{label, pattern->getNameStr().str(),
// dispatcher_.fetchLabel(pattern->getDecl())});
dispatcher_.emit(NamedPatternsTrap{label, pattern->getNameStr().str()});
}
private:
SwiftDispatcher& dispatcher;
};
void visitTypedPattern(swift::TypedPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
assert(pattern->getSubPattern() && "expect TypedPattern to have a SubPattern");
dispatcher_.emit(TypedPatternsTrap{label, dispatcher_.fetchLabel(pattern->getSubPattern())});
if (auto typeRepr = pattern->getTypeRepr()) {
dispatcher_.emit(
TypedPatternTypeReprsTrap{label, dispatcher_.fetchLabel(pattern->getTypeRepr())});
}
}
void visitTuplePattern(swift::TuplePattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
dispatcher_.emit(TuplePatternsTrap{label});
auto i = 0u;
for (auto p : pattern->getElements()) {
dispatcher_.emit(
TuplePatternElementsTrap{label, i++, dispatcher_.fetchLabel(p.getPattern())});
}
}
void visitAnyPattern(swift::AnyPattern* pattern) {
dispatcher_.emit(AnyPatternsTrap{dispatcher_.assignNewLabel(pattern)});
}
void visitBindingPattern(swift::BindingPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
assert(pattern->getSubPattern() && "expect BindingPattern to have a SubPattern");
dispatcher_.emit(BindingPatternsTrap{label, dispatcher_.fetchLabel(pattern->getSubPattern())});
}
void visitEnumElementPattern(swift::EnumElementPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
dispatcher_.emit(
EnumElementPatternsTrap{label, dispatcher_.fetchLabel(pattern->getElementDecl())});
if (auto subPattern = pattern->getSubPattern()) {
dispatcher_.emit(EnumElementPatternSubPatternsTrap{
label, dispatcher_.fetchLabel(pattern->getSubPattern())});
}
}
void visitOptionalSomePattern(swift::OptionalSomePattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
assert(pattern->getSubPattern() && "expect BindingPattern to have a SubPattern");
dispatcher_.emit(
OptionalSomePatternsTrap{label, dispatcher_.fetchLabel(pattern->getSubPattern())});
}
void visitIsPattern(swift::IsPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
dispatcher_.emit(IsPatternsTrap{label});
if (auto typeRepr = pattern->getCastTypeRepr()) {
dispatcher_.emit(IsPatternCastTypeReprsTrap{label, dispatcher_.fetchLabel(typeRepr)});
}
if (auto subPattern = pattern->getSubPattern()) {
dispatcher_.emit(IsPatternSubPatternsTrap{label, dispatcher_.fetchLabel(subPattern)});
}
}
void visitExprPattern(swift::ExprPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
assert(pattern->getSubExpr() && "expect ExprPattern to have SubExpr");
dispatcher_.emit(ExprPatternsTrap{label, dispatcher_.fetchLabel(pattern->getSubExpr())});
}
void visitParenPattern(swift::ParenPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
assert(pattern->getSubPattern() && "expect ParenPattern to have SubPattern");
dispatcher_.emit(ParenPatternsTrap{label, dispatcher_.fetchLabel(pattern->getSubPattern())});
}
void visitBoolPattern(swift::BoolPattern* pattern) {
auto label = dispatcher_.assignNewLabel(pattern);
dispatcher_.emit(BoolPatternsTrap{label, pattern->getValue()});
}
};
} // namespace codeql

View File

@@ -1,39 +1,223 @@
#pragma once
#include "swift/extractor/SwiftDispatcher.h"
#include <swift/AST/ASTVisitor.h>
#include "swift/extractor/visitors/VisitorBase.h"
namespace codeql {
namespace detail {
// swift code lacks default implementations of visitor for some entities. We can add those here
// while we do not have yet all implemented. This is a simplified version of the corresponding Expr
// code in swift/AST/ASTVisitor.h
template <typename CrtpSubclass>
class PatchedStmtVisitor : public swift::StmtVisitor<CrtpSubclass> {
class StmtVisitor : public AstVisitorBase<StmtVisitor> {
public:
#define ABSTRACT_STMT(CLASS, PARENT) \
void visit##CLASS##Stmt(swift::CLASS##Stmt* E) { \
return static_cast<CrtpSubclass*>(this)->visit##PARENT(E); \
using AstVisitorBase<StmtVisitor>::AstVisitorBase;
void visitLabeledStmt(swift::LabeledStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
}
#define STMT(CLASS, PARENT) ABSTRACT_STMT(CLASS, PARENT)
#include "swift/AST/StmtNodes.def"
};
} // namespace detail
void visitStmtCondition(swift::StmtCondition* cond) {
auto label = dispatcher_.assignNewLabel(cond);
dispatcher_.emit(StmtConditionsTrap{label});
unsigned index = 0;
for (const auto& cond : *cond) {
auto condLabel = dispatcher_.createLabel<ConditionElementTag>();
dispatcher_.attachLocation(cond, condLabel);
dispatcher_.emit(ConditionElementsTrap{condLabel});
dispatcher_.emit(StmtConditionElementsTrap{label, index++, condLabel});
if (auto boolean = cond.getBooleanOrNull()) {
auto elementLabel = dispatcher_.fetchLabel(boolean);
dispatcher_.emit(ConditionElementBooleansTrap{condLabel, elementLabel});
} else if (auto pattern = cond.getPatternOrNull()) {
auto patternLabel = dispatcher_.fetchLabel(pattern);
auto initilizerLabel = dispatcher_.fetchLabel(cond.getInitializer());
dispatcher_.emit(ConditionElementPatternsTrap{condLabel, patternLabel});
dispatcher_.emit(ConditionElementInitializersTrap{condLabel, initilizerLabel});
}
/// TODO: Implement availability
}
}
class StmtVisitor : public detail::PatchedStmtVisitor<StmtVisitor> {
public:
// SwiftDispatcher should outlive the StmtVisitor
StmtVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
void visitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
}
template <typename E>
void visitStmt(E* stmt) {
dispatcher.TBD<swift::Stmt>(stmt, "Stmt");
void visitCaseLabelItem(swift::CaseLabelItem* labelItem) {
auto label = dispatcher_.assignNewLabel(labelItem);
assert(labelItem->getPattern() && "CaseLabelItem has Pattern");
dispatcher_.emit(CaseLabelItemsTrap{label, dispatcher_.fetchLabel(labelItem->getPattern())});
}
void visitBraceStmt(swift::BraceStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(BraceStmtsTrap{label});
auto i = 0u;
for (auto& e : stmt->getElements()) {
dispatcher_.emit(BraceStmtElementsTrap{label, i++, dispatcher_.fetchLabel(e)});
}
}
void visitReturnStmt(swift::ReturnStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(ReturnStmtsTrap{label});
if (stmt->hasResult()) {
auto resultLabel = dispatcher_.fetchLabel(stmt->getResult());
dispatcher_.emit(ReturnStmtResultsTrap{label, resultLabel});
}
}
void visitForEachStmt(swift::ForEachStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
assert(stmt->getBody() && "ForEachStmt has getBody()");
assert(stmt->getSequence() && "ForEachStmt has getSequence()");
assert(stmt->getPattern() && "ForEachStmt has getPattern()");
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
auto sequenceLabel = dispatcher_.fetchLabel(stmt->getSequence());
auto patternLabel = dispatcher_.fetchLabel(stmt->getPattern());
emitLabeledStmt(stmt, label);
dispatcher_.emit(ForEachStmtsTrap{label, patternLabel, sequenceLabel, bodyLabel});
if (auto where = stmt->getWhere()) {
auto whereLabel = dispatcher_.fetchLabel(where);
dispatcher_.emit(ForEachStmtWheresTrap{label, whereLabel});
}
}
void visitIfStmt(swift::IfStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
auto thenLabel = dispatcher_.fetchLabel(stmt->getThenStmt());
dispatcher_.emit(IfStmtsTrap{label, thenLabel});
if (auto* elseStmt = stmt->getElseStmt()) {
auto elseLabel = dispatcher_.fetchLabel(elseStmt);
dispatcher_.emit(IfStmtElsesTrap{label, elseLabel});
}
}
void visitBreakStmt(swift::BreakStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(BreakStmtsTrap{label});
if (auto* target = stmt->getTarget()) {
auto targetlabel = dispatcher_.fetchLabel(target);
dispatcher_.emit(BreakStmtTargetsTrap{label, targetlabel});
}
auto targetName = stmt->getTargetName();
if (!targetName.empty()) {
dispatcher_.emit(BreakStmtTargetNamesTrap{label, targetName.str().str()});
}
}
void visitContinueStmt(swift::ContinueStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
dispatcher_.emit(ContinueStmtsTrap{label});
if (auto* target = stmt->getTarget()) {
auto targetlabel = dispatcher_.fetchLabel(target);
dispatcher_.emit(ContinueStmtTargetsTrap{label, targetlabel});
}
auto targetName = stmt->getTargetName();
if (!targetName.empty()) {
dispatcher_.emit(ContinueStmtTargetNamesTrap{label, targetName.str().str()});
}
}
void visitWhileStmt(swift::WhileStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
dispatcher_.emit(WhileStmtsTrap{label, dispatcher_.fetchLabel(stmt->getBody())});
}
void visitRepeatWhileStmt(swift::RepeatWhileStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
auto condLabel = dispatcher_.fetchLabel(stmt->getCond());
dispatcher_.emit(RepeatWhileStmtsTrap{label, condLabel, bodyLabel});
}
void visitDoCatchStmt(swift::DoCatchStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(DoCatchStmtsTrap{label, bodyLabel});
auto i = 0u;
for (auto* stmtCatch : stmt->getCatches()) {
dispatcher_.emit(DoCatchStmtCatchesTrap{label, i++, dispatcher_.fetchLabel(stmtCatch)});
}
}
void visitCaseStmt(swift::CaseStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(CaseStmtsTrap{label, bodyLabel});
auto i = 0u;
for (auto& item : stmt->getMutableCaseLabelItems()) {
dispatcher_.emit(CaseStmtLabelsTrap{label, i++, dispatcher_.fetchLabel(&item)});
}
if (stmt->hasCaseBodyVariables()) {
auto i = 0u;
for (auto* var : stmt->getCaseBodyVariables()) {
dispatcher_.emit(CaseStmtVariablesTrap{label, i++, dispatcher_.fetchLabel(var)});
}
}
}
void visitGuardStmt(swift::GuardStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
emitLabeledConditionalStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(GuardStmtsTrap{label, bodyLabel});
}
void visitThrowStmt(swift::ThrowStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto subExprLabel = dispatcher_.fetchLabel(stmt->getSubExpr());
dispatcher_.emit(ThrowStmtsTrap{label, subExprLabel});
}
void visitDeferStmt(swift::DeferStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBodyAsWritten());
dispatcher_.emit(DeferStmtsTrap{label, bodyLabel});
}
void visitDoStmt(swift::DoStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto bodyLabel = dispatcher_.fetchLabel(stmt->getBody());
dispatcher_.emit(DoStmtsTrap{label, bodyLabel});
}
void visitSwitchStmt(swift::SwitchStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
emitLabeledStmt(stmt, label);
auto subjectLabel = dispatcher_.fetchLabel(stmt->getSubjectExpr());
dispatcher_.emit(SwitchStmtsTrap{label, subjectLabel});
auto i = 0u;
for (auto* c : stmt->getCases()) {
dispatcher_.emit(SwitchStmtCasesTrap{label, i++, dispatcher_.fetchLabel(c)});
}
}
void visitFallthroughStmt(swift::FallthroughStmt* stmt) {
auto label = dispatcher_.assignNewLabel(stmt);
auto sourceLabel = dispatcher_.fetchLabel(stmt->getFallthroughSource());
auto destLabel = dispatcher_.fetchLabel(stmt->getFallthroughDest());
dispatcher_.emit(FallthroughStmtsTrap{label, sourceLabel, destLabel});
}
private:
SwiftDispatcher& dispatcher;
void emitLabeledStmt(const swift::LabeledStmt* stmt, TrapLabel<LabeledStmtTag> label) {
if (stmt->getLabelInfo()) {
dispatcher_.emit(LabeledStmtLabelsTrap{label, stmt->getLabelInfo().Name.str().str()});
}
}
void emitLabeledConditionalStmt(swift::LabeledConditionalStmt* stmt,
TrapLabel<LabeledConditionalStmtTag> label) {
auto condLabel = dispatcher_.fetchLabel(stmt->getCondPointer());
dispatcher_.emit(LabeledConditionalStmtsTrap{label, condLabel});
}
};
} // namespace codeql

View File

@@ -0,0 +1,12 @@
#pragma once
#include "swift/extractor/visitors/VisitorBase.h"
namespace codeql {
class TypeReprVisitor : public AstVisitorBase<TypeReprVisitor> {
public:
using AstVisitorBase<TypeReprVisitor>::AstVisitorBase;
};
} // namespace codeql

View File

@@ -1,22 +1,233 @@
#pragma once
#include "swift/extractor/SwiftDispatcher.h"
#include <swift/AST/TypeVisitor.h>
#include "swift/extractor/visitors/VisitorBase.h"
namespace codeql {
class TypeVisitor : public swift::TypeVisitor<TypeVisitor> {
class TypeVisitor : public TypeVisitorBase<TypeVisitor> {
public:
// SwiftDispatcher should outlive the TypeVisitor
TypeVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
using TypeVisitorBase<TypeVisitor>::TypeVisitorBase;
template <typename E>
void visitType(E* type) {
dispatcher.TBD<swift::TypeBase>(type, "Type");
void visit(swift::TypeBase* type) {
TypeVisitorBase<TypeVisitor>::visit(type);
auto label = dispatcher_.fetchLabel(type);
auto canonical = type->getCanonicalType().getPointer();
auto canonicalLabel = (canonical == type) ? label : dispatcher_.fetchLabel(canonical);
dispatcher_.emit(TypesTrap{label, type->getString(), canonicalLabel});
}
void visitProtocolType(swift::ProtocolType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(ProtocolTypesTrap{label});
emitAnyGenericType(type, label);
}
void visitEnumType(swift::EnumType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(EnumTypesTrap{label});
emitAnyGenericType(type, label);
}
void visitStructType(swift::StructType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(StructTypesTrap{label});
emitAnyGenericType(type, label);
}
void visitClassType(swift::ClassType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(ClassTypesTrap{label});
emitAnyGenericType(type, label);
}
void visitFunctionType(swift::FunctionType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(FunctionTypesTrap{label});
emitAnyFunctionType(type, label);
}
void visitTupleType(swift::TupleType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(TupleTypesTrap{label});
auto i = 0u;
for (const auto& e : type->getElements()) {
auto typeTag = dispatcher_.fetchLabel(e.getType());
dispatcher_.emit(TupleTypeTypesTrap{label, i, typeTag});
if (e.hasName()) {
dispatcher_.emit(TupleTypeNamesTrap{label, i, e.getName().str().str()});
}
++i;
}
}
void visitBoundGenericEnumType(swift::BoundGenericEnumType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(BoundGenericEnumTypesTrap{label});
emitBoundGenericType(type, label);
}
void visitMetatypeType(swift::MetatypeType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(MetatypeTypesTrap{label});
}
void visitExistentialMetatypeType(swift::ExistentialMetatypeType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(ExistentialMetatypeTypesTrap{label});
}
void visitBoundGenericStructType(swift::BoundGenericStructType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(BoundGenericStructTypesTrap{label});
emitBoundGenericType(type, label);
}
void visitTypeAliasType(swift::TypeAliasType* type) {
auto label = dispatcher_.assignNewLabel(type);
assert(type->getDecl() && "expect TypeAliasType to have Decl");
dispatcher_.emit(TypeAliasTypesTrap{label, dispatcher_.fetchLabel(type->getDecl())});
}
void visitBuiltinIntegerLiteralType(swift::BuiltinIntegerLiteralType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(BuiltinIntegerLiteralTypesTrap{label});
}
void visitBuiltinFloatType(swift::BuiltinFloatType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(BuiltinFloatTypesTrap{label});
}
void visitBuiltinIntegerType(swift::BuiltinIntegerType* type) {
auto label = dispatcher_.assignNewLabel(type);
auto width = type->getWidth();
if (width.isFixedWidth()) {
dispatcher_.emit(BuiltinIntegerTypeWidthsTrap{label, width.getFixedWidth()});
}
dispatcher_.emit(BuiltinIntegerTypesTrap{label});
}
void visitBoundGenericClassType(swift::BoundGenericClassType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(BoundGenericClassTypesTrap{label});
emitBoundGenericType(type, label);
}
void visitDependentMemberType(swift::DependentMemberType* type) {
auto label = dispatcher_.assignNewLabel(type);
assert(type->getBase() && "expect TypeAliasType to have Base");
assert(type->getAssocType() && "expect TypeAliasType to have AssocType");
auto baseLabel = dispatcher_.fetchLabel(type->getBase());
auto assocTypeDeclLabel = dispatcher_.fetchLabel(type->getAssocType());
dispatcher_.emit(DependentMemberTypesTrap{label, baseLabel, assocTypeDeclLabel});
}
void visitParenType(swift::ParenType* type) {
auto label = dispatcher_.assignNewLabel(type);
assert(type->getUnderlyingType() && "expect ParenType to have UnderlyingType");
auto typeLabel = dispatcher_.fetchLabel(type->getUnderlyingType());
dispatcher_.emit(ParenTypesTrap{label, typeLabel});
}
void visitUnarySyntaxSugarType(swift::UnarySyntaxSugarType* type) {
auto label = dispatcher_.assignNewLabel(type);
emitUnarySyntaxSugarType(type, label);
}
void visitOptionalType(swift::OptionalType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(OptionalTypesTrap{label});
emitUnarySyntaxSugarType(type, label);
}
void visitArraySliceType(swift::ArraySliceType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(ArraySliceTypesTrap{label});
emitUnarySyntaxSugarType(type, label);
}
void visitDictionaryType(swift::DictionaryType* type) {
auto label = dispatcher_.assignNewLabel(type);
auto keyLabel = dispatcher_.fetchLabel(type->getKeyType());
auto valueLabel = dispatcher_.fetchLabel(type->getValueType());
dispatcher_.emit(DictionaryTypesTrap{label, keyLabel, valueLabel});
}
void visitGenericFunctionType(swift::GenericFunctionType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(GenericFunctionTypesTrap{label});
emitAnyFunctionType(type, label);
auto i = 0u;
for (auto p : type->getGenericParams()) {
dispatcher_.emit(GenericFunctionTypeGenericParamsTrap{label, i++, dispatcher_.fetchLabel(p)});
}
}
void visitGenericTypeParamType(swift::GenericTypeParamType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(GenericTypeParamTypesTrap{label, type->getName().str().str()});
}
void visitLValueType(swift::LValueType* type) {
auto label = dispatcher_.assignNewLabel(type);
assert(type->getObjectType() && "expect LValueType to have ObjectType");
dispatcher_.emit(LValueTypesTrap{label, dispatcher_.fetchLabel(type->getObjectType())});
}
void visitPrimaryArchetypeType(swift::PrimaryArchetypeType* type) {
auto label = dispatcher_.assignNewLabel(type);
assert(type->getInterfaceType() && "expect PrimaryArchetypeType to have InterfaceType");
dispatcher_.emit(
PrimaryArchetypeTypesTrap{label, dispatcher_.fetchLabel(type->getInterfaceType())});
}
void visitUnboundGenericType(swift::UnboundGenericType* type) {
auto label = dispatcher_.assignNewLabel(type);
dispatcher_.emit(UnboundGenericTypesTrap{label});
emitAnyGenericType(type, label);
}
void visitBoundGenericType(swift::BoundGenericType* type) {
auto label = dispatcher_.assignNewLabel(type);
emitBoundGenericType(type, label);
}
private:
SwiftDispatcher& dispatcher;
void emitUnarySyntaxSugarType(const swift::UnarySyntaxSugarType* type,
TrapLabel<UnarySyntaxSugarTypeTag> label) {
assert(type->getBaseType() && "expect UnarySyntaxSugarType to have BaseType");
dispatcher_.emit(UnarySyntaxSugarTypesTrap{label, dispatcher_.fetchLabel(type->getBaseType())});
}
void emitAnyFunctionType(const swift::AnyFunctionType* type,
TrapLabel<AnyFunctionTypeTag> label) {
assert(type->getResult() && "expect FunctionType to have Result");
dispatcher_.emit(AnyFunctionTypesTrap{label, dispatcher_.fetchLabel(type->getResult())});
auto i = 0u;
for (const auto& p : type->getParams()) {
assert(p.getPlainType() && "expect Param to have PlainType");
dispatcher_.emit(
AnyFunctionTypeParamTypesTrap{label, i, dispatcher_.fetchLabel(p.getPlainType())});
if (p.hasLabel()) {
dispatcher_.emit(AnyFunctionTypeParamLabelsTrap{label, i, p.getLabel().str().str()});
}
++i;
}
}
void emitBoundGenericType(swift::BoundGenericType* type, TrapLabel<BoundGenericTypeTag> label) {
auto i = 0u;
for (const auto& t : type->getGenericArgs()) {
dispatcher_.emit(BoundGenericTypeArgTypesTrap{label, i++, dispatcher_.fetchLabel(t)});
}
emitAnyGenericType(type, label);
}
void emitAnyGenericType(swift::AnyGenericType* type, TrapLabel<AnyGenericTypeTag> label) {
assert(type->getDecl() && "expect AnyGenericType to have Decl");
dispatcher_.emit(AnyGenericTypesTrap{label, dispatcher_.fetchLabel(type->getDecl())});
if (auto parent = type->getParent()) {
dispatcher_.emit(AnyGenericTypeParentsTrap{label, dispatcher_.fetchLabel(parent)});
}
}
};
} // namespace codeql

View File

@@ -0,0 +1,65 @@
#pragma once
#include <swift/AST/ASTVisitor.h>
#include <swift/AST/TypeVisitor.h>
#include "swift/extractor/SwiftDispatcher.h"
namespace codeql {
namespace detail {
class VisitorBase {
protected:
SwiftDispatcher& dispatcher_;
public:
// SwiftDispatcher should outlive this instance
VisitorBase(SwiftDispatcher& dispatcher) : dispatcher_{dispatcher} {}
};
} // namespace detail
// 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); }
// 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 {
public:
using VisitorBase::VisitorBase;
#define DECL(CLASS, PARENT) DEFAULT(Decl, CLASS, PARENT)
#include "swift/AST/DeclNodes.def"
#define STMT(CLASS, PARENT) DEFAULT(Stmt, CLASS, PARENT)
#include "swift/AST/StmtNodes.def"
#define EXPR(CLASS, PARENT) DEFAULT(Expr, CLASS, PARENT)
#include "swift/AST/ExprNodes.def"
#define PATTERN(CLASS, PARENT) DEFAULT(Pattern, CLASS, PARENT)
#include "swift/AST/PatternNodes.def"
#define TYPEREPR(CLASS, PARENT) DEFAULT(TypeRepr, CLASS, PARENT)
#include "swift/AST/TypeReprNodes.def"
};
// base class for our type visitor, getting a SwiftDispatcher member and default emission for
// unknown/TBD types. Like `swift::TypeVisitor`, this uses CRTP (the Curiously Recurring Template
// Pattern)
template <typename CrtpSubclass>
class TypeVisitorBase : public swift::TypeVisitor<CrtpSubclass>, protected detail::VisitorBase {
public:
using VisitorBase::VisitorBase;
#define TYPE(CLASS, PARENT) DEFAULT(Type, CLASS, PARENT)
#include "swift/AST/TypeNodes.def"
};
#undef DEFAULT
} // namespace codeql

View File

@@ -19,10 +19,12 @@ import codeql.swift.elements.expr.Argument
import codeql.swift.elements.expr.ArrayExpr
import codeql.swift.elements.type.ArraySliceType
import codeql.swift.elements.expr.ArrayToPointerExpr
import codeql.swift.elements.typerepr.ArrayTypeRepr
import codeql.swift.elements.expr.ArrowExpr
import codeql.swift.elements.expr.AssignExpr
import codeql.swift.elements.decl.AssociatedTypeDecl
import codeql.swift.elements.AstNode
import codeql.swift.elements.typerepr.AttributedTypeRepr
import codeql.swift.elements.expr.AutoClosureExpr
import codeql.swift.elements.expr.AwaitExpr
import codeql.swift.elements.expr.BinaryExpr
@@ -65,6 +67,10 @@ import codeql.swift.elements.expr.CodeCompletionExpr
import codeql.swift.elements.expr.CoerceExpr
import codeql.swift.elements.expr.CollectionExpr
import codeql.swift.elements.expr.CollectionUpcastConversionExpr
import codeql.swift.elements.typerepr.CompileTimeConstTypeRepr
import codeql.swift.elements.typerepr.ComponentIdentTypeRepr
import codeql.swift.elements.typerepr.CompositionTypeRepr
import codeql.swift.elements.typerepr.CompoundIdentTypeRepr
import codeql.swift.elements.decl.ConcreteFuncDecl
import codeql.swift.elements.decl.ConcreteVarDecl
import codeql.swift.elements.stmt.ConditionElement
@@ -85,6 +91,7 @@ import codeql.swift.elements.decl.DestructorDecl
import codeql.swift.elements.expr.DestructureTupleExpr
import codeql.swift.elements.expr.DictionaryExpr
import codeql.swift.elements.type.DictionaryType
import codeql.swift.elements.typerepr.DictionaryTypeRepr
import codeql.swift.elements.expr.DifferentiableFunctionExpr
import codeql.swift.elements.expr.DifferentiableFunctionExtractOriginalExpr
import codeql.swift.elements.expr.DiscardAssignmentExpr
@@ -109,9 +116,11 @@ import codeql.swift.elements.type.EnumType
import codeql.swift.elements.expr.ErasureExpr
import codeql.swift.elements.expr.ErrorExpr
import codeql.swift.elements.type.ErrorType
import codeql.swift.elements.typerepr.ErrorTypeRepr
import codeql.swift.elements.expr.ExistentialMetatypeToObjectExpr
import codeql.swift.elements.type.ExistentialMetatypeType
import codeql.swift.elements.type.ExistentialType
import codeql.swift.elements.typerepr.ExistentialTypeRepr
import codeql.swift.elements.expr.ExplicitCastExpr
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.pattern.ExprPattern
@@ -119,6 +128,7 @@ import codeql.swift.elements.decl.ExtensionDecl
import codeql.swift.elements.stmt.FailStmt
import codeql.swift.elements.stmt.FallthroughStmt
import codeql.swift.elements.File
import codeql.swift.elements.typerepr.FixedTypeRepr
import codeql.swift.elements.expr.FloatLiteralExpr
import codeql.swift.elements.stmt.ForEachStmt
import codeql.swift.elements.expr.ForceTryExpr
@@ -128,27 +138,33 @@ import codeql.swift.elements.expr.ForeignObjectConversionExpr
import codeql.swift.elements.decl.FuncDecl
import codeql.swift.elements.expr.FunctionConversionExpr
import codeql.swift.elements.type.FunctionType
import codeql.swift.elements.typerepr.FunctionTypeRepr
import codeql.swift.elements.decl.GenericContext
import codeql.swift.elements.type.GenericFunctionType
import codeql.swift.elements.typerepr.GenericIdentTypeRepr
import codeql.swift.elements.decl.GenericTypeDecl
import codeql.swift.elements.decl.GenericTypeParamDecl
import codeql.swift.elements.type.GenericTypeParamType
import codeql.swift.elements.stmt.GuardStmt
import codeql.swift.elements.typerepr.IdentTypeRepr
import codeql.swift.elements.expr.IdentityExpr
import codeql.swift.elements.decl.IfConfigDecl
import codeql.swift.elements.expr.IfExpr
import codeql.swift.elements.stmt.IfStmt
import codeql.swift.elements.expr.ImplicitConversionExpr
import codeql.swift.elements.typerepr.ImplicitlyUnwrappedOptionalTypeRepr
import codeql.swift.elements.decl.ImportDecl
import codeql.swift.elements.expr.InOutExpr
import codeql.swift.elements.expr.InOutToPointerExpr
import codeql.swift.elements.type.InOutType
import codeql.swift.elements.typerepr.InOutTypeRepr
import codeql.swift.elements.decl.InfixOperatorDecl
import codeql.swift.elements.expr.InjectIntoOptionalExpr
import codeql.swift.elements.expr.IntegerLiteralExpr
import codeql.swift.elements.expr.InterpolatedStringLiteralExpr
import codeql.swift.elements.expr.IsExpr
import codeql.swift.elements.pattern.IsPattern
import codeql.swift.elements.typerepr.IsolatedTypeRepr
import codeql.swift.elements.decl.IterableDeclContext
import codeql.swift.elements.expr.KeyPathApplicationExpr
import codeql.swift.elements.expr.KeyPathDotExpr
@@ -170,9 +186,11 @@ import codeql.swift.elements.expr.MakeTemporarilyEscapableExpr
import codeql.swift.elements.expr.MemberRefExpr
import codeql.swift.elements.expr.MetatypeConversionExpr
import codeql.swift.elements.type.MetatypeType
import codeql.swift.elements.typerepr.MetatypeTypeRepr
import codeql.swift.elements.decl.MissingMemberDecl
import codeql.swift.elements.decl.ModuleDecl
import codeql.swift.elements.type.ModuleType
import codeql.swift.elements.typerepr.NamedOpaqueReturnTypeRepr
import codeql.swift.elements.pattern.NamedPattern
import codeql.swift.elements.type.NestedArchetypeType
import codeql.swift.elements.expr.NilLiteralExpr
@@ -183,6 +201,7 @@ import codeql.swift.elements.expr.NumberLiteralExpr
import codeql.swift.elements.expr.ObjCSelectorExpr
import codeql.swift.elements.expr.ObjectLiteralExpr
import codeql.swift.elements.expr.OneWayExpr
import codeql.swift.elements.typerepr.OpaqueReturnTypeRepr
import codeql.swift.elements.type.OpaqueTypeArchetypeType
import codeql.swift.elements.decl.OpaqueTypeDecl
import codeql.swift.elements.expr.OpaqueValueExpr
@@ -193,9 +212,11 @@ import codeql.swift.elements.expr.OptionalEvaluationExpr
import codeql.swift.elements.pattern.OptionalSomePattern
import codeql.swift.elements.expr.OptionalTryExpr
import codeql.swift.elements.type.OptionalType
import codeql.swift.elements.typerepr.OptionalTypeRepr
import codeql.swift.elements.expr.OtherConstructorDeclRefExpr
import codeql.swift.elements.expr.OverloadSetRefExpr
import codeql.swift.elements.expr.OverloadedDeclRefExpr
import codeql.swift.elements.typerepr.OwnedTypeRepr
import codeql.swift.elements.decl.ParamDecl
import codeql.swift.elements.expr.ParenExpr
import codeql.swift.elements.pattern.ParenPattern
@@ -203,6 +224,7 @@ import codeql.swift.elements.type.ParenType
import codeql.swift.elements.pattern.Pattern
import codeql.swift.elements.decl.PatternBindingDecl
import codeql.swift.elements.type.PlaceholderType
import codeql.swift.elements.typerepr.PlaceholderTypeRepr
import codeql.swift.elements.expr.PointerToPointerExpr
import codeql.swift.elements.decl.PostfixOperatorDecl
import codeql.swift.elements.expr.PostfixUnaryExpr
@@ -217,6 +239,7 @@ import codeql.swift.elements.type.ProtocolCompositionType
import codeql.swift.elements.decl.ProtocolDecl
import codeql.swift.elements.expr.ProtocolMetatypeToObjectExpr
import codeql.swift.elements.type.ProtocolType
import codeql.swift.elements.typerepr.ProtocolTypeRepr
import codeql.swift.elements.expr.RebindSelfInConstructorExpr
import codeql.swift.elements.type.ReferenceStorageType
import codeql.swift.elements.expr.RegexLiteralExpr
@@ -225,10 +248,14 @@ import codeql.swift.elements.stmt.ReturnStmt
import codeql.swift.elements.expr.SelfApplyExpr
import codeql.swift.elements.type.SequenceArchetypeType
import codeql.swift.elements.expr.SequenceExpr
import codeql.swift.elements.typerepr.SharedTypeRepr
import codeql.swift.elements.type.SilBlockStorageType
import codeql.swift.elements.type.SilBoxType
import codeql.swift.elements.typerepr.SilBoxTypeRepr
import codeql.swift.elements.type.SilFunctionType
import codeql.swift.elements.type.SilTokenType
import codeql.swift.elements.typerepr.SimpleIdentTypeRepr
import codeql.swift.elements.typerepr.SpecifierTypeRepr
import codeql.swift.elements.stmt.Stmt
import codeql.swift.elements.stmt.StmtCondition
import codeql.swift.elements.expr.StringLiteralExpr
@@ -250,6 +277,7 @@ import codeql.swift.elements.expr.TupleElementExpr
import codeql.swift.elements.expr.TupleExpr
import codeql.swift.elements.pattern.TuplePattern
import codeql.swift.elements.type.TupleType
import codeql.swift.elements.typerepr.TupleTypeRepr
import codeql.swift.elements.type.Type
import codeql.swift.elements.decl.TypeAliasDecl
import codeql.swift.elements.type.TypeAliasType
@@ -262,8 +290,6 @@ import codeql.swift.elements.type.UnarySyntaxSugarType
import codeql.swift.elements.type.UnboundGenericType
import codeql.swift.elements.expr.UnderlyingToOpaqueExpr
import codeql.swift.elements.expr.UnevaluatedInstanceExpr
import codeql.swift.elements.UnknownAstNode
import codeql.swift.elements.type.UnknownType
import codeql.swift.elements.type.UnmanagedStorageType
import codeql.swift.elements.type.UnownedStorageType
import codeql.swift.elements.expr.UnresolvedDeclRefExpr

View File

@@ -1,4 +1,11 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.Element
class Element extends ElementBase { }
class Element extends ElementBase {
override string toString() { result = getPrimaryQlClasses() }
}
class UnknownElement extends Element {
UnknownElement() { isUnknown() }
override string toString() { result = "TBD (" + getPrimaryQlClasses() + ")" }
}

View File

@@ -1,5 +0,0 @@
private import codeql.swift.generated.UnknownAstNode
class UnknownAstNode extends UnknownAstNodeBase {
override string toString() { result = getName() }
}

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.type.UnknownType
class UnknownType extends UnknownTypeBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ArrayTypeRepr
class ArrayTypeRepr extends ArrayTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.AttributedTypeRepr
class AttributedTypeRepr extends AttributedTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.CompileTimeConstTypeRepr
class CompileTimeConstTypeRepr extends CompileTimeConstTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ComponentIdentTypeRepr
class ComponentIdentTypeRepr extends ComponentIdentTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.CompositionTypeRepr
class CompositionTypeRepr extends CompositionTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.CompoundIdentTypeRepr
class CompoundIdentTypeRepr extends CompoundIdentTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.DictionaryTypeRepr
class DictionaryTypeRepr extends DictionaryTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ErrorTypeRepr
class ErrorTypeRepr extends ErrorTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ExistentialTypeRepr
class ExistentialTypeRepr extends ExistentialTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.FixedTypeRepr
class FixedTypeRepr extends FixedTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.FunctionTypeRepr
class FunctionTypeRepr extends FunctionTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.GenericIdentTypeRepr
class GenericIdentTypeRepr extends GenericIdentTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.IdentTypeRepr
class IdentTypeRepr extends IdentTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ImplicitlyUnwrappedOptionalTypeRepr
class ImplicitlyUnwrappedOptionalTypeRepr extends ImplicitlyUnwrappedOptionalTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.InOutTypeRepr
class InOutTypeRepr extends InOutTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.IsolatedTypeRepr
class IsolatedTypeRepr extends IsolatedTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.MetatypeTypeRepr
class MetatypeTypeRepr extends MetatypeTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.NamedOpaqueReturnTypeRepr
class NamedOpaqueReturnTypeRepr extends NamedOpaqueReturnTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.OpaqueReturnTypeRepr
class OpaqueReturnTypeRepr extends OpaqueReturnTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.OptionalTypeRepr
class OptionalTypeRepr extends OptionalTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.OwnedTypeRepr
class OwnedTypeRepr extends OwnedTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.PlaceholderTypeRepr
class PlaceholderTypeRepr extends PlaceholderTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.ProtocolTypeRepr
class ProtocolTypeRepr extends ProtocolTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.SharedTypeRepr
class SharedTypeRepr extends SharedTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.SilBoxTypeRepr
class SilBoxTypeRepr extends SilBoxTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.SimpleIdentTypeRepr
class SimpleIdentTypeRepr extends SimpleIdentTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.SpecifierTypeRepr
class SpecifierTypeRepr extends SpecifierTypeReprBase { }

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.typerepr.TupleTypeRepr
class TupleTypeRepr extends TupleTypeReprBase { }

View File

@@ -13,4 +13,6 @@ class ElementBase extends @element {
or
result = getResolveStep().resolve()
}
predicate isUnknown() { element_is_unknown(this) }
}

View File

@@ -1,12 +0,0 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.Decl
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.pattern.Pattern
import codeql.swift.elements.stmt.Stmt
import codeql.swift.elements.typerepr.TypeRepr
class UnknownAstNodeBase extends @unknown_ast_node, Decl, Expr, Pattern, Stmt, TypeRepr {
override string getAPrimaryQlClass() { result = "UnknownAstNode" }
string getName() { unknown_ast_nodes(this, result) }
}

View File

@@ -1,6 +1,16 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.OperatorDecl
import codeql.swift.elements.decl.PrecedenceGroupDecl
class InfixOperatorDeclBase extends @infix_operator_decl, OperatorDecl {
override string getAPrimaryQlClass() { result = "InfixOperatorDecl" }
PrecedenceGroupDecl getPrecedenceGroup() {
exists(PrecedenceGroupDecl x |
infix_operator_decl_precedence_groups(this, x) and
result = x.resolve()
)
}
predicate hasPrecedenceGroup() { exists(getPrecedenceGroup()) }
}

View File

@@ -1,4 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.Decl
class OperatorDeclBase extends @operator_decl, Decl { }
class OperatorDeclBase extends @operator_decl, Decl {
string getName() { operator_decls(this, result) }
}

View File

@@ -1,6 +1,18 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.Type
import codeql.swift.elements.decl.ValueDecl
class TypeDeclBase extends @type_decl, ValueDecl {
string getName() { type_decls(this, result) }
Type getBaseType(int index) {
exists(Type x |
type_decl_base_types(this, index, x) and
result = x.resolve()
)
}
Type getABaseType() { result = getBaseType(_) }
int getNumberOfBaseTypes() { result = count(getABaseType()) }
}

View File

@@ -1,5 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.AbstractStorageDecl
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.pattern.Pattern
import codeql.swift.elements.type.Type
class VarDeclBase extends @var_decl, AbstractStorageDecl {
@@ -11,4 +13,31 @@ class VarDeclBase extends @var_decl, AbstractStorageDecl {
result = x.resolve()
)
}
Type getAttachedPropertyWrapperType() {
exists(Type x |
var_decl_attached_property_wrapper_types(this, x) and
result = x.resolve()
)
}
predicate hasAttachedPropertyWrapperType() { exists(getAttachedPropertyWrapperType()) }
Pattern getParentPattern() {
exists(Pattern x |
var_decl_parent_patterns(this, x) and
result = x.resolve()
)
}
predicate hasParentPattern() { exists(getParentPattern()) }
Expr getParentInitializer() {
exists(Expr x |
var_decl_parent_initializers(this, x) and
result = x.resolve()
)
}
predicate hasParentInitializer() { exists(getParentInitializer()) }
}

View File

@@ -2,20 +2,21 @@
import codeql.swift.elements.stmt.BraceStmt
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.stmt.LabeledStmt
import codeql.swift.elements.pattern.Pattern
class ForEachStmtBase extends @for_each_stmt, LabeledStmt {
override string getAPrimaryQlClass() { result = "ForEachStmt" }
BraceStmt getBody() {
exists(BraceStmt x |
for_each_stmts(this, x, _) and
Pattern getPattern() {
exists(Pattern x |
for_each_stmts(this, x, _, _) and
result = x.resolve()
)
}
Expr getSequence() {
exists(Expr x |
for_each_stmts(this, _, x) and
for_each_stmts(this, _, x, _) and
result = x.resolve()
)
}
@@ -28,4 +29,11 @@ class ForEachStmtBase extends @for_each_stmt, LabeledStmt {
}
predicate hasWhere() { exists(getWhere()) }
BraceStmt getBody() {
exists(BraceStmt x |
for_each_stmts(this, _, _, x) and
result = x.resolve()
)
}
}

View File

@@ -1,4 +1,16 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.NominalOrBoundGenericNominalType
import codeql.swift.elements.type.Type
class BoundGenericTypeBase extends @bound_generic_type, NominalOrBoundGenericNominalType { }
class BoundGenericTypeBase extends @bound_generic_type, NominalOrBoundGenericNominalType {
Type getArgType(int index) {
exists(Type x |
bound_generic_type_arg_types(this, index, x) and
result = x.resolve()
)
}
Type getAnArgType() { result = getArgType(_) }
int getNumberOfArgTypes() { result = count(getAnArgType()) }
}

View File

@@ -3,4 +3,8 @@ import codeql.swift.elements.type.AnyBuiltinIntegerType
class BuiltinIntegerTypeBase extends @builtin_integer_type, AnyBuiltinIntegerType {
override string getAPrimaryQlClass() { result = "BuiltinIntegerType" }
int getWidth() { builtin_integer_type_widths(this, result) }
predicate hasWidth() { exists(getWidth()) }
}

View File

@@ -1,14 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.ClassDecl
import codeql.swift.elements.type.NominalType
class ClassTypeBase extends @class_type, NominalType {
override string getAPrimaryQlClass() { result = "ClassType" }
ClassDecl getDecl() {
exists(ClassDecl x |
class_types(this, x) and
result = x.resolve()
)
}
}

View File

@@ -1,6 +1,21 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.AssociatedTypeDecl
import codeql.swift.elements.type.Type
class DependentMemberTypeBase extends @dependent_member_type, Type {
override string getAPrimaryQlClass() { result = "DependentMemberType" }
Type getBaseType() {
exists(Type x |
dependent_member_types(this, x, _) and
result = x.resolve()
)
}
AssociatedTypeDecl getAssociatedTypeDecl() {
exists(AssociatedTypeDecl x |
dependent_member_types(this, _, x) and
result = x.resolve()
)
}
}

View File

@@ -1,6 +1,21 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.SyntaxSugarType
import codeql.swift.elements.type.Type
class DictionaryTypeBase extends @dictionary_type, SyntaxSugarType {
override string getAPrimaryQlClass() { result = "DictionaryType" }
Type getKeyType() {
exists(Type x |
dictionary_types(this, x, _) and
result = x.resolve()
)
}
Type getValueType() {
exists(Type x |
dictionary_types(this, _, x) and
result = x.resolve()
)
}
}

View File

@@ -1,6 +1,14 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.SugarType
import codeql.swift.elements.type.Type
class ParenTypeBase extends @paren_type, SugarType {
override string getAPrimaryQlClass() { result = "ParenType" }
Type getType() {
exists(Type x |
paren_types(this, x) and
result = x.resolve()
)
}
}

View File

@@ -1,14 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.NominalType
import codeql.swift.elements.decl.StructDecl
class StructTypeBase extends @struct_type, NominalType {
override string getAPrimaryQlClass() { result = "StructType" }
StructDecl getDecl() {
exists(StructDecl x |
struct_types(this, x) and
result = x.resolve()
)
}
}

View File

@@ -3,4 +3,21 @@ import codeql.swift.elements.type.Type
class TupleTypeBase extends @tuple_type, Type {
override string getAPrimaryQlClass() { result = "TupleType" }
Type getType(int index) {
exists(Type x |
tuple_type_types(this, index, x) and
result = x.resolve()
)
}
Type getAType() { result = getType(_) }
int getNumberOfTypes() { result = count(getAType()) }
string getName(int index) { tuple_type_names(this, index, result) }
string getAName() { result = getName(_) }
int getNumberOfNames() { result = count(getAName()) }
}

View File

@@ -1,6 +1,14 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.SugarType
import codeql.swift.elements.decl.TypeAliasDecl
class TypeAliasTypeBase extends @type_alias_type, SugarType {
override string getAPrimaryQlClass() { result = "TypeAliasType" }
TypeAliasDecl getDecl() {
exists(TypeAliasDecl x |
type_alias_types(this, x) and
result = x.resolve()
)
}
}

View File

@@ -1,4 +1,12 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.SyntaxSugarType
import codeql.swift.elements.type.Type
class UnarySyntaxSugarTypeBase extends @unary_syntax_sugar_type, SyntaxSugarType { }
class UnarySyntaxSugarTypeBase extends @unary_syntax_sugar_type, SyntaxSugarType {
Type getBaseType() {
exists(Type x |
unary_syntax_sugar_types(this, x) and
result = x.resolve()
)
}
}

View File

@@ -1,8 +0,0 @@
// generated by codegen/codegen.py
import codeql.swift.elements.type.Type
class UnknownTypeBase extends @unknown_type, Type {
override string getAPrimaryQlClass() { result = "UnknownType" }
string getName() { unknown_types(this, result) }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class ArrayTypeReprBase extends @array_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "ArrayTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class AttributedTypeReprBase extends @attributed_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "AttributedTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.SpecifierTypeRepr
class CompileTimeConstTypeReprBase extends @compile_time_const_type_repr, SpecifierTypeRepr {
override string getAPrimaryQlClass() { result = "CompileTimeConstTypeRepr" }
}

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.IdentTypeRepr
class ComponentIdentTypeReprBase extends @component_ident_type_repr, IdentTypeRepr { }

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class CompositionTypeReprBase extends @composition_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "CompositionTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.IdentTypeRepr
class CompoundIdentTypeReprBase extends @compound_ident_type_repr, IdentTypeRepr {
override string getAPrimaryQlClass() { result = "CompoundIdentTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class DictionaryTypeReprBase extends @dictionary_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "DictionaryTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class ErrorTypeReprBase extends @error_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "ErrorTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class ExistentialTypeReprBase extends @existential_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "ExistentialTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class FixedTypeReprBase extends @fixed_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "FixedTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class FunctionTypeReprBase extends @function_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "FunctionTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.ComponentIdentTypeRepr
class GenericIdentTypeReprBase extends @generic_ident_type_repr, ComponentIdentTypeRepr {
override string getAPrimaryQlClass() { result = "GenericIdentTypeRepr" }
}

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class IdentTypeReprBase extends @ident_type_repr, TypeRepr { }

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class ImplicitlyUnwrappedOptionalTypeReprBase extends @implicitly_unwrapped_optional_type_repr,
TypeRepr {
override string getAPrimaryQlClass() { result = "ImplicitlyUnwrappedOptionalTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.SpecifierTypeRepr
class InOutTypeReprBase extends @in_out_type_repr, SpecifierTypeRepr {
override string getAPrimaryQlClass() { result = "InOutTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.SpecifierTypeRepr
class IsolatedTypeReprBase extends @isolated_type_repr, SpecifierTypeRepr {
override string getAPrimaryQlClass() { result = "IsolatedTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class MetatypeTypeReprBase extends @metatype_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "MetatypeTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class NamedOpaqueReturnTypeReprBase extends @named_opaque_return_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "NamedOpaqueReturnTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class OpaqueReturnTypeReprBase extends @opaque_return_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "OpaqueReturnTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class OptionalTypeReprBase extends @optional_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "OptionalTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.SpecifierTypeRepr
class OwnedTypeReprBase extends @owned_type_repr, SpecifierTypeRepr {
override string getAPrimaryQlClass() { result = "OwnedTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class PlaceholderTypeReprBase extends @placeholder_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "PlaceholderTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class ProtocolTypeReprBase extends @protocol_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "ProtocolTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.SpecifierTypeRepr
class SharedTypeReprBase extends @shared_type_repr, SpecifierTypeRepr {
override string getAPrimaryQlClass() { result = "SharedTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class SilBoxTypeReprBase extends @sil_box_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "SilBoxTypeRepr" }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.ComponentIdentTypeRepr
class SimpleIdentTypeReprBase extends @simple_ident_type_repr, ComponentIdentTypeRepr {
override string getAPrimaryQlClass() { result = "SimpleIdentTypeRepr" }
}

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class SpecifierTypeReprBase extends @specifier_type_repr, TypeRepr { }

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py
import codeql.swift.elements.typerepr.TypeRepr
class TupleTypeReprBase extends @tuple_type_repr, TypeRepr {
override string getAPrimaryQlClass() { result = "TupleTypeRepr" }
}

Some files were not shown because too many files have changed in this diff Show More