Merge pull request #10175 from github/redsun82/swift-missing-extractions

Swift: fix missing extractions
This commit is contained in:
Paolo Tranquilli
2022-08-26 14:09:09 +02:00
committed by GitHub
21 changed files with 333 additions and 150 deletions

View File

@@ -1121,6 +1121,8 @@ ModuleDecl:
_extends: TypeDecl
is_builtin_module: predicate
is_system_module: predicate
imported_modules: ModuleDecl*
exported_modules: ModuleDecl*
ConstructorRefCallExpr:
_extends: SelfApplyExpr

View File

@@ -0,0 +1,71 @@
#pragma once
#include <array>
namespace codeql {
constexpr std::array swiftBuiltins = {
"zeroInitializer",
"BridgeObject",
"Word",
"NativeObject",
"RawPointer",
"Executor",
"Job",
"RawUnsafeContinuation",
"addressof",
"initialize",
"reinterpretCast",
"Int1",
"Int8",
"Int16",
"Int32",
"Int64",
"IntLiteral",
"FPIEEE16",
"FPIEEE32",
"FPIEEE64",
"FPIEEE80",
"Vec2xInt8",
"Vec4xInt8",
"Vec8xInt8",
"Vec16xInt8",
"Vec32xInt8",
"Vec64xInt8",
"Vec2xInt16",
"Vec4xInt16",
"Vec8xInt16",
"Vec16xInt16",
"Vec32xInt16",
"Vec64xInt16",
"Vec2xInt32",
"Vec4xInt32",
"Vec8xInt32",
"Vec16xInt32",
"Vec32xInt32",
"Vec64xInt32",
"Vec2xInt64",
"Vec4xInt64",
"Vec8xInt64",
"Vec16xInt64",
"Vec32xInt64",
"Vec64xInt64",
"Vec2xFPIEEE16",
"Vec4xFPIEEE16",
"Vec8xFPIEEE16",
"Vec16xFPIEEE16",
"Vec32xFPIEEE16",
"Vec64xFPIEEE16",
"Vec2xFPIEEE32",
"Vec4xFPIEEE32",
"Vec8xFPIEEE32",
"Vec16xFPIEEE32",
"Vec32xFPIEEE32",
"Vec64xFPIEEE32",
"Vec2xFPIEEE64",
"Vec4xFPIEEE64",
"Vec8xFPIEEE64",
"Vec16xFPIEEE64",
"Vec32xFPIEEE64",
"Vec64xFPIEEE64",
};
}

View File

@@ -6,15 +6,12 @@
#include <queue>
#include <swift/AST/SourceFile.h>
#include <swift/Basic/FileTypes.h>
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Path.h>
#include <swift/AST/Builtins.h>
#include "swift/extractor/trap/generated/TrapClasses.h"
#include "swift/extractor/trap/TrapDomain.h"
#include "swift/extractor/visitors/SwiftVisitor.h"
#include "swift/extractor/TargetTrapFile.h"
#include "swift/extractor/SwiftBuiltinSymbols.h"
using namespace codeql;
using namespace std::string_literals;
@@ -65,7 +62,40 @@ static std::string getFilename(swift::ModuleDecl& module, swift::SourceFile* pri
filename += module.getName().str();
return filename;
}
return module.getModuleFilename().str();
if (module.isBuiltinModule()) {
// The Builtin module has an empty filename, let's fix that
return "/__Builtin__";
}
auto filename = module.getModuleFilename().str();
// there is a special case of a module without an actual filename reporting `<imports>`: in this
// case we want to avoid the `<>` characters, in case a dirty DB is imported on Windows
if (filename == "<imports>") {
return "/__imports__";
}
return filename;
}
/* The builtin module is special, as it does not publish any top-level declaration
* It creates (and caches) declarations on demand when a lookup is carried out
* (see BuiltinUnit in swift/AST/FileUnit.h for the cache details, and getBuiltinValueDecl in
* swift/AST/Builtins.h for the creation details)
* As we want to create the Builtin trap file once and for all so that it works for other
* extraction runs, rather than collecting what we need we pre-populate the builtin trap with
* what we expect. This list might need thus to be expanded.
* Notice, that while swift/AST/Builtins.def has a list of builtin symbols, it does not contain
* all information required to instantiate builtin variants.
* Other possible approaches:
* * create one trap per builtin declaration when encountered
* * expand the list to all possible builtins (of which there are a lot)
*/
static void getBuiltinDecls(swift::ModuleDecl& builtinModule,
llvm::SmallVector<swift::Decl*>& decls) {
llvm::SmallVector<swift::ValueDecl*> values;
for (auto symbol : swiftBuiltins) {
builtinModule.lookupValue(builtinModule.getASTContext().getIdentifier(symbol),
swift::NLKind::QualifiedLookup, values);
}
decls.insert(decls.end(), values.begin(), values.end());
}
static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& module,
@@ -74,16 +104,19 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
ret.push_back(&module);
if (primaryFile) {
primaryFile->getTopLevelDecls(ret);
} else if (module.isBuiltinModule()) {
getBuiltinDecls(module, ret);
} else {
module.getTopLevelDecls(ret);
}
return ret;
}
static void extractDeclarations(const SwiftExtractorConfiguration& config,
swift::CompilerInstance& compiler,
swift::ModuleDecl& module,
swift::SourceFile* primaryFile = nullptr) {
static std::unordered_set<swift::ModuleDecl*> extractDeclarations(
const SwiftExtractorConfiguration& config,
swift::CompilerInstance& compiler,
swift::ModuleDecl& module,
swift::SourceFile* primaryFile = nullptr) {
auto filename = getFilename(module, primaryFile);
// The extractor can be called several times from different processes with
@@ -92,7 +125,7 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
auto trapTarget = createTargetTrapFile(config, filename);
if (!trapTarget) {
// another process arrived first, nothing to do for us
return;
return {};
}
TrapDomain trap{*trapTarget};
@@ -116,6 +149,7 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
for (auto& comment : comments) {
visitor.extract(comment);
}
return std::move(visitor).getEncounteredModules();
}
static std::unordered_set<std::string> collectInputFilenames(swift::CompilerInstance& compiler) {
@@ -132,40 +166,27 @@ static std::unordered_set<std::string> collectInputFilenames(swift::CompilerInst
return sourceFiles;
}
static std::unordered_set<swift::ModuleDecl*> collectModules(swift::CompilerInstance& compiler) {
// getASTContext().getLoadedModules() does not provide all the modules available within the
// program.
// We need to iterate over all the imported modules (recursively) to see the whole "universe."
std::unordered_set<swift::ModuleDecl*> allModules;
std::queue<swift::ModuleDecl*> worklist;
for (auto& [_, module] : compiler.getASTContext().getLoadedModules()) {
worklist.push(module);
allModules.insert(module);
static std::vector<swift::ModuleDecl*> collectLoadedModules(swift::CompilerInstance& compiler) {
std::vector<swift::ModuleDecl*> ret;
for (const auto& [id, module] : compiler.getASTContext().getLoadedModules()) {
std::ignore = id;
ret.push_back(module);
}
while (!worklist.empty()) {
auto module = worklist.front();
worklist.pop();
llvm::SmallVector<swift::ImportedModule> importedModules;
// TODO: we may need more than just Exported ones
module->getImportedModules(importedModules, swift::ModuleDecl::ImportFilterKind::Exported);
for (auto& imported : importedModules) {
if (allModules.count(imported.importedModule) == 0) {
worklist.push(imported.importedModule);
allModules.insert(imported.importedModule);
}
}
}
return allModules;
return ret;
}
void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
swift::CompilerInstance& compiler) {
auto inputFiles = collectInputFilenames(compiler);
auto modules = collectModules(compiler);
std::vector<swift::ModuleDecl*> todo = collectLoadedModules(compiler);
std::unordered_set<swift::ModuleDecl*> seen{todo.begin(), todo.end()};
for (auto& module : modules) {
while (!todo.empty()) {
auto module = todo.back();
todo.pop_back();
llvm::errs() << "processing module " << module->getName() << '\n';
bool isFromSourceFile = false;
std::unordered_set<swift::ModuleDecl*> encounteredModules;
for (auto file : module->getFiles()) {
auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
if (!sourceFile) {
@@ -176,10 +197,16 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
continue;
}
archiveFile(config, *sourceFile);
extractDeclarations(config, compiler, *module, sourceFile);
encounteredModules = extractDeclarations(config, compiler, *module, sourceFile);
}
if (!isFromSourceFile) {
extractDeclarations(config, compiler, *module);
encounteredModules = extractDeclarations(config, compiler, *module);
}
for (auto encountered : encounteredModules) {
if (seen.count(encountered) == 0) {
todo.push_back(encountered);
seen.insert(encountered);
}
}
}
}

View File

@@ -55,6 +55,10 @@ class SwiftDispatcher {
}
}
const std::unordered_set<swift::ModuleDecl*> getEncounteredModules() && {
return std::move(encounteredModules);
}
template <typename Entry>
void emit(const Entry& entry) {
trap.emit(entry);
@@ -228,8 +232,16 @@ class SwiftDispatcher {
// - extracting a primary source file: in this mode, we extract several files belonging to the
// same module one by one. In this mode, we restrict emission only to the same file ignoring
// all the other files.
// This is also used to register the modules we encounter.
// TODO calls to this function should be taken away from `DeclVisitor` and moved around with a
// clearer separation between naming entities (some decls, all types), deciding whether to emit
// them and finally visiting emitting the contents of the entity (which should remain in the
// visitors). Then this double responsibility (carrying out the test and registering encountered
// modules) should also be cleared out
bool shouldEmitDeclBody(const swift::Decl& decl) {
if (decl.getModuleContext() != &currentModule) {
auto module = decl.getModuleContext();
if (module != &currentModule) {
encounteredModules.insert(module);
return false;
}
// ModuleDecl is a special case: if it passed the previous test, it is the current module
@@ -333,6 +345,7 @@ class SwiftDispatcher {
Store::Handle waitingForNewLabel{std::monostate{}};
swift::ModuleDecl& currentModule;
swift::SourceFile* currentPrimarySourceFile;
std::unordered_set<swift::ModuleDecl*> encounteredModules;
};
} // namespace codeql

View File

@@ -22,31 +22,31 @@ std::string constructName(const swift::DeclName& declName) {
}
} // namespace
std::variant<codeql::ConcreteFuncDecl, codeql::ConcreteFuncDeclsTrap>
DeclVisitor::translateFuncDecl(const swift::FuncDecl& decl) {
auto ret = createNamedEntryOr<ConcreteFuncDeclsTrap>(decl);
if (auto entry = get_if<ConcreteFuncDecl>(&ret)) {
std::optional<codeql::ConcreteFuncDecl> DeclVisitor::translateFuncDecl(
const swift::FuncDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillAbstractFunctionDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::ConstructorDecl, codeql::ConstructorDeclsTrap>
DeclVisitor::translateConstructorDecl(const swift::ConstructorDecl& decl) {
auto ret = createNamedEntryOr<ConstructorDeclsTrap>(decl);
if (auto entry = get_if<ConstructorDecl>(&ret)) {
std::optional<codeql::ConstructorDecl> DeclVisitor::translateConstructorDecl(
const swift::ConstructorDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillAbstractFunctionDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::DestructorDecl, codeql::DestructorDeclsTrap>
DeclVisitor::translateDestructorDecl(const swift::DestructorDecl& decl) {
auto ret = createNamedEntryOr<DestructorDeclsTrap>(decl);
if (auto entry = get_if<DestructorDecl>(&ret)) {
std::optional<codeql::DestructorDecl> DeclVisitor::translateDestructorDecl(
const swift::DestructorDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillAbstractFunctionDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
codeql::PrefixOperatorDecl DeclVisitor::translatePrefixOperatorDecl(
@@ -124,40 +124,37 @@ std::optional<codeql::ConcreteVarDecl> DeclVisitor::translateVarDecl(const swift
return entry;
}
std::variant<codeql::StructDecl, codeql::StructDeclsTrap> DeclVisitor::translateStructDecl(
const swift::StructDecl& decl) {
auto ret = createNamedEntryOr<StructDeclsTrap>(decl);
if (auto entry = get_if<StructDecl>(&ret)) {
std::optional<codeql::StructDecl> DeclVisitor::translateStructDecl(const swift::StructDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillNominalTypeDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::ClassDecl, codeql::ClassDeclsTrap> DeclVisitor::translateClassDecl(
const swift::ClassDecl& decl) {
auto ret = createNamedEntryOr<ClassDeclsTrap>(decl);
if (auto entry = get_if<ClassDecl>(&ret)) {
std::optional<codeql::ClassDecl> DeclVisitor::translateClassDecl(const swift::ClassDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillNominalTypeDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::EnumDecl, codeql::EnumDeclsTrap> DeclVisitor::translateEnumDecl(
const swift::EnumDecl& decl) {
auto ret = createNamedEntryOr<EnumDeclsTrap>(decl);
if (auto entry = get_if<EnumDecl>(&ret)) {
std::optional<codeql::EnumDecl> DeclVisitor::translateEnumDecl(const swift::EnumDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillNominalTypeDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::ProtocolDecl, codeql::ProtocolDeclsTrap> DeclVisitor::translateProtocolDecl(
std::optional<codeql::ProtocolDecl> DeclVisitor::translateProtocolDecl(
const swift::ProtocolDecl& decl) {
auto ret = createNamedEntryOr<ProtocolDeclsTrap>(decl);
if (auto entry = get_if<ProtocolDecl>(&ret)) {
if (auto entry = createNamedEntry(decl)) {
fillNominalTypeDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
codeql::EnumCaseDecl DeclVisitor::translateEnumCaseDecl(const swift::EnumCaseDecl& decl) {
@@ -166,17 +163,18 @@ codeql::EnumCaseDecl DeclVisitor::translateEnumCaseDecl(const swift::EnumCaseDec
return entry;
}
std::variant<codeql::EnumElementDecl, codeql::EnumElementDeclsTrap>
DeclVisitor::translateEnumElementDecl(const swift::EnumElementDecl& decl) {
auto ret = createNamedEntryOr<EnumElementDeclsTrap>(decl);
std::visit([&](auto& entry) { entry.name = decl.getNameStr().str(); }, ret);
if (auto entry = get_if<EnumElementDecl>(&ret)) {
if (decl.hasParameterList()) {
entry->params = dispatcher_.fetchRepeatedLabels(*decl.getParameterList());
}
fillValueDecl(decl, *entry);
std::optional<codeql::EnumElementDecl> DeclVisitor::translateEnumElementDecl(
const swift::EnumElementDecl& decl) {
auto entry = createNamedEntry(decl);
if (!entry) {
return std::nullopt;
}
return ret;
entry->name = decl.getNameStr().str();
if (decl.hasParameterList()) {
entry->params = dispatcher_.fetchRepeatedLabels(*decl.getParameterList());
}
fillValueDecl(decl, *entry);
return entry;
}
codeql::GenericTypeParamDecl DeclVisitor::translateGenericTypeParamDecl(
@@ -187,45 +185,46 @@ codeql::GenericTypeParamDecl DeclVisitor::translateGenericTypeParamDecl(
return entry;
}
std::variant<codeql::AssociatedTypeDecl, codeql::AssociatedTypeDeclsTrap>
DeclVisitor::translateAssociatedTypeDecl(const swift::AssociatedTypeDecl& decl) {
auto ret = createNamedEntryOr<AssociatedTypeDeclsTrap>(decl);
if (auto entry = get_if<AssociatedTypeDecl>(&ret)) {
std::optional<codeql::AssociatedTypeDecl> DeclVisitor::translateAssociatedTypeDecl(
const swift::AssociatedTypeDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillTypeDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::TypeAliasDecl, codeql::TypeAliasDeclsTrap> DeclVisitor::translateTypeAliasDecl(
std::optional<codeql::TypeAliasDecl> DeclVisitor::translateTypeAliasDecl(
const swift::TypeAliasDecl& decl) {
auto ret = createNamedEntryOr<TypeAliasDeclsTrap>(decl);
if (auto entry = get_if<TypeAliasDecl>(&ret)) {
if (auto entry = createNamedEntry(decl)) {
fillTypeDecl(decl, *entry);
return entry;
}
return ret;
return std::nullopt;
}
std::variant<codeql::AccessorDecl, codeql::AccessorDeclsTrap> DeclVisitor::translateAccessorDecl(
std::optional<codeql::AccessorDecl> DeclVisitor::translateAccessorDecl(
const swift::AccessorDecl& decl) {
auto ret = createNamedEntryOr<AccessorDeclsTrap>(decl);
if (auto entry = get_if<AccessorDecl>(&ret)) {
switch (decl.getAccessorKind()) {
case swift::AccessorKind::Get:
entry->is_getter = true;
break;
case swift::AccessorKind::Set:
entry->is_setter = true;
break;
case swift::AccessorKind::WillSet:
entry->is_will_set = true;
break;
case swift::AccessorKind::DidSet:
entry->is_did_set = true;
break;
}
fillAbstractFunctionDecl(decl, *entry);
auto entry = createNamedEntry(decl);
if (!entry) {
return std::nullopt;
}
return ret;
switch (decl.getAccessorKind()) {
case swift::AccessorKind::Get:
entry->is_getter = true;
break;
case swift::AccessorKind::Set:
entry->is_setter = true;
break;
case swift::AccessorKind::WillSet:
entry->is_will_set = true;
break;
case swift::AccessorKind::DidSet:
entry->is_did_set = true;
break;
}
fillAbstractFunctionDecl(decl, *entry);
return entry;
}
std::optional<codeql::SubscriptDecl> DeclVisitor::translateSubscriptDecl(
@@ -265,6 +264,17 @@ std::optional<codeql::ModuleDecl> DeclVisitor::translateModuleDecl(const swift::
}
entry->is_builtin_module = decl.isBuiltinModule();
entry->is_system_module = decl.isSystemModule();
using K = swift::ModuleDecl::ImportFilterKind;
llvm::SmallVector<swift::ImportedModule> imports;
decl.getImportedModules(imports, K::Default);
for (const auto& import : imports) {
entry->imported_modules.push_back(dispatcher_.fetchLabel(import.importedModule));
}
imports.clear();
decl.getImportedModules(imports, K::Exported);
for (const auto& import : imports) {
entry->exported_modules.push_back(dispatcher_.fetchLabel(import.importedModule));
}
fillTypeDecl(decl, *entry);
return entry;
}

View File

@@ -20,12 +20,10 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
dispatcher_.emit(translateIfConfigClause(*clause));
}
std::variant<codeql::ConcreteFuncDecl, codeql::ConcreteFuncDeclsTrap> translateFuncDecl(
const swift::FuncDecl& decl);
std::variant<codeql::ConstructorDecl, codeql::ConstructorDeclsTrap> translateConstructorDecl(
std::optional<codeql::ConcreteFuncDecl> translateFuncDecl(const swift::FuncDecl& decl);
std::optional<codeql::ConstructorDecl> translateConstructorDecl(
const swift::ConstructorDecl& decl);
std::variant<codeql::DestructorDecl, codeql::DestructorDeclsTrap> translateDestructorDecl(
const swift::DestructorDecl& decl);
std::optional<codeql::DestructorDecl> translateDestructorDecl(const swift::DestructorDecl& decl);
codeql::PrefixOperatorDecl translatePrefixOperatorDecl(const swift::PrefixOperatorDecl& decl);
codeql::PostfixOperatorDecl translatePostfixOperatorDecl(const swift::PostfixOperatorDecl& decl);
codeql::InfixOperatorDecl translateInfixOperatorDecl(const swift::InfixOperatorDecl& decl);
@@ -34,25 +32,19 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
codeql::TopLevelCodeDecl translateTopLevelCodeDecl(const swift::TopLevelCodeDecl& decl);
codeql::PatternBindingDecl translatePatternBindingDecl(const swift::PatternBindingDecl& decl);
std::optional<codeql::ConcreteVarDecl> translateVarDecl(const swift::VarDecl& decl);
std::variant<codeql::StructDecl, codeql::StructDeclsTrap> translateStructDecl(
const swift::StructDecl& decl);
std::variant<codeql::ClassDecl, codeql::ClassDeclsTrap> translateClassDecl(
const swift::ClassDecl& decl);
std::variant<codeql::EnumDecl, codeql::EnumDeclsTrap> translateEnumDecl(
const swift::EnumDecl& decl);
std::variant<codeql::ProtocolDecl, codeql::ProtocolDeclsTrap> translateProtocolDecl(
const swift::ProtocolDecl& decl);
std::optional<codeql::StructDecl> translateStructDecl(const swift::StructDecl& decl);
std::optional<codeql::ClassDecl> translateClassDecl(const swift::ClassDecl& decl);
std::optional<codeql::EnumDecl> translateEnumDecl(const swift::EnumDecl& decl);
std::optional<codeql::ProtocolDecl> translateProtocolDecl(const swift::ProtocolDecl& decl);
codeql::EnumCaseDecl translateEnumCaseDecl(const swift::EnumCaseDecl& decl);
std::variant<codeql::EnumElementDecl, codeql::EnumElementDeclsTrap> translateEnumElementDecl(
std::optional<codeql::EnumElementDecl> translateEnumElementDecl(
const swift::EnumElementDecl& decl);
codeql::GenericTypeParamDecl translateGenericTypeParamDecl(
const swift::GenericTypeParamDecl& decl);
std::variant<codeql::AssociatedTypeDecl, codeql::AssociatedTypeDeclsTrap>
translateAssociatedTypeDecl(const swift::AssociatedTypeDecl& decl);
std::variant<codeql::TypeAliasDecl, codeql::TypeAliasDeclsTrap> translateTypeAliasDecl(
const swift::TypeAliasDecl& decl);
std::variant<codeql::AccessorDecl, codeql::AccessorDeclsTrap> translateAccessorDecl(
const swift::AccessorDecl& decl);
std::optional<codeql::AssociatedTypeDecl> translateAssociatedTypeDecl(
const swift::AssociatedTypeDecl& decl);
std::optional<codeql::TypeAliasDecl> translateTypeAliasDecl(const swift::TypeAliasDecl& decl);
std::optional<codeql::AccessorDecl> translateAccessorDecl(const swift::AccessorDecl& decl);
std::optional<codeql::SubscriptDecl> translateSubscriptDecl(const swift::SubscriptDecl& decl);
codeql::ExtensionDecl translateExtensionDecl(const swift::ExtensionDecl& decl);
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
@@ -86,17 +78,6 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
return entry;
}
template <typename T, typename D, typename... Args>
std::variant<TrapClassOf<D>, T> createNamedEntryOr(const D& decl) {
auto id = dispatcher_.assignNewLabel(decl, mangledName(decl));
if (dispatcher_.shouldEmitDeclBody(decl)) {
TrapClassOf<D> entry{id};
fillDecl(decl, entry);
return entry;
}
return T{id};
}
template <typename D>
TrapClassOf<D> createEntry(const D& decl) {
TrapClassOf<D> entry{dispatcher_.template assignNewLabel(decl)};

View File

@@ -11,6 +11,7 @@ namespace codeql {
class SwiftVisitor : private SwiftDispatcher {
public:
using SwiftDispatcher::getEncounteredModules;
using SwiftDispatcher::SwiftDispatcher;
template <typename T>

View File

@@ -1,5 +1,6 @@
| file://:0:0:0:0 | A |
| file://:0:0:0:0 | B |
| file://:0:0:0:0 | PackageDescription |
| file://:0:0:0:0 | __ObjC |
| file://:0:0:0:0 | main |
| file://:0:0:0:0 | partial_modules |

View File

@@ -1398,6 +1398,10 @@ module Raw {
predicate isBuiltinModule() { module_decl_is_builtin_module(this) }
predicate isSystemModule() { module_decl_is_system_module(this) }
ModuleDecl getImportedModule(int index) { module_decl_imported_modules(this, index, result) }
ModuleDecl getExportedModule(int index) { module_decl_exported_modules(this, index, result) }
}
class NumberLiteralExpr extends @number_literal_expr, BuiltinLiteralExpr { }

View File

@@ -1,6 +1,7 @@
// generated by codegen/codegen.py
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.decl.ModuleDecl
import codeql.swift.elements.decl.TypeDecl
class ModuleDeclBase extends Synth::TModuleDecl, TypeDecl {
@@ -13,4 +14,34 @@ class ModuleDeclBase extends Synth::TModuleDecl, TypeDecl {
predicate isSystemModule() {
Synth::convertModuleDeclToRaw(this).(Raw::ModuleDecl).isSystemModule()
}
ModuleDecl getImmediateImportedModule(int index) {
result =
Synth::convertModuleDeclFromRaw(Synth::convertModuleDeclToRaw(this)
.(Raw::ModuleDecl)
.getImportedModule(index))
}
final ModuleDecl getImportedModule(int index) {
result = getImmediateImportedModule(index).resolve()
}
final ModuleDecl getAnImportedModule() { result = getImportedModule(_) }
final int getNumberOfImportedModules() { result = count(getAnImportedModule()) }
ModuleDecl getImmediateExportedModule(int index) {
result =
Synth::convertModuleDeclFromRaw(Synth::convertModuleDeclToRaw(this)
.(Raw::ModuleDecl)
.getExportedModule(index))
}
final ModuleDecl getExportedModule(int index) {
result = getImmediateExportedModule(index).resolve()
}
final ModuleDecl getAnExportedModule() { result = getExportedModule(_) }
final int getNumberOfExportedModules() { result = count(getAnExportedModule()) }
}

View File

@@ -2116,6 +2116,20 @@ module_decl_is_system_module( //dir=decl
int id: @module_decl ref
);
#keyset[id, index]
module_decl_imported_modules( //dir=decl
int id: @module_decl ref,
int index: int ref,
int imported_module: @module_decl ref
);
#keyset[id, index]
module_decl_exported_modules( //dir=decl
int id: @module_decl ref,
int index: int ref,
int exported_module: @module_decl ref
);
constructor_ref_call_exprs( //dir=expr
unique int id: @constructor_ref_call_expr
);

View File

@@ -1,2 +1,3 @@
| file://:0:0:0:0 | Foo | getModule: | file://:0:0:0:0 | Foo | getInterfaceType: | module<Foo> | getName: | Foo | isBuiltinModule: | no | isSystemModule: | no |
| file://:0:0:0:0 | __ObjC | getModule: | file://:0:0:0:0 | __ObjC | getInterfaceType: | module<__ObjC> | getName: | __ObjC | isBuiltinModule: | no | isSystemModule: | no |
| file://:0:0:0:0 | default_module_name | getModule: | file://:0:0:0:0 | default_module_name | getInterfaceType: | module<default_module_name> | getName: | default_module_name | isBuiltinModule: | no | isSystemModule: | no |

View File

@@ -0,0 +1,7 @@
| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift |
| file://:0:0:0:0 | Foo | 1 | file://:0:0:0:0 | _Concurrency |
| file://:0:0:0:0 | Foo | 2 | file://:0:0:0:0 | SwiftOnoneSupport |
| file://:0:0:0:0 | __ObjC | 0 | file://:0:0:0:0 | Swift |
| file://:0:0:0:0 | default_module_name | 0 | file://:0:0:0:0 | Swift |
| file://:0:0:0:0 | default_module_name | 1 | file://:0:0:0:0 | _Concurrency |
| file://:0:0:0:0 | default_module_name | 2 | file://:0:0:0:0 | SwiftOnoneSupport |

View File

@@ -0,0 +1 @@
| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from ModuleDecl x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getExportedModule(index)

View File

@@ -0,0 +1,7 @@
| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift |
| file://:0:0:0:0 | Foo | 1 | file://:0:0:0:0 | _Concurrency |
| file://:0:0:0:0 | Foo | 2 | file://:0:0:0:0 | SwiftOnoneSupport |
| file://:0:0:0:0 | __ObjC | 0 | file://:0:0:0:0 | Swift |
| file://:0:0:0:0 | default_module_name | 0 | file://:0:0:0:0 | Swift |
| file://:0:0:0:0 | default_module_name | 1 | file://:0:0:0:0 | _Concurrency |
| file://:0:0:0:0 | default_module_name | 2 | file://:0:0:0:0 | SwiftOnoneSupport |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from ModuleDecl x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getImportedModule(index)

View File

@@ -1 +1,2 @@
//codeql-extractor-options: -module-name Foo
@_exported import Swift

View File

@@ -1,5 +1,4 @@
| Builtin.BridgeObject | getName: | Builtin.BridgeObject | getCanonicalType: | Builtin.BridgeObject |
| Builtin.DefaultActorStorage | getName: | Builtin.DefaultActorStorage | getCanonicalType: | Builtin.DefaultActorStorage |
| Builtin.Executor | getName: | Builtin.Executor | getCanonicalType: | Builtin.Executor |
| Builtin.FPIEEE32 | getName: | Builtin.FPIEEE32 | getCanonicalType: | Builtin.FPIEEE32 |
| Builtin.FPIEEE64 | getName: | Builtin.FPIEEE64 | getCanonicalType: | Builtin.FPIEEE64 |
@@ -8,4 +7,3 @@
| Builtin.NativeObject | getName: | Builtin.NativeObject | getCanonicalType: | Builtin.NativeObject |
| Builtin.RawPointer | getName: | Builtin.RawPointer | getCanonicalType: | Builtin.RawPointer |
| Builtin.RawUnsafeContinuation | getName: | Builtin.RawUnsafeContinuation | getCanonicalType: | Builtin.RawUnsafeContinuation |
| Builtin.UnsafeValueBuffer | getName: | Builtin.UnsafeValueBuffer | getCanonicalType: | Builtin.UnsafeValueBuffer |

View File

@@ -4,11 +4,9 @@ func foo(
_: Builtin.FPIEEE32,
_: Builtin.FPIEEE64,
_: Builtin.BridgeObject,
_: Builtin.DefaultActorStorage,
_: Builtin.Executor,
_: Builtin.Job,
_: Builtin.NativeObject,
_: Builtin.RawPointer,
_: Builtin.RawUnsafeContinuation,
_: Builtin.UnsafeValueBuffer
_: Builtin.Executor,
_: Builtin.Job,
_: Builtin.RawUnsafeContinuation
) {}

View File

@@ -1,2 +1,3 @@
| module<Foo> | getName: | module<Foo> | getCanonicalType: | module<Foo> | getModule: | file://:0:0:0:0 | Foo |
| module<__ObjC> | getName: | module<__ObjC> | getCanonicalType: | module<__ObjC> | getModule: | file://:0:0:0:0 | __ObjC |
| module<default_module_name> | getName: | module<default_module_name> | getCanonicalType: | module<default_module_name> | getModule: | file://:0:0:0:0 | default_module_name |