зеркало из https://github.com/github/codeql.git
Merge pull request #12433 from github/alexdenisov+redsun82/tuple-mangling
Swift: properly identify types and declarations in trap files via mangling
This commit is contained in:
Коммит
67cd25184a
|
@ -14,7 +14,6 @@
|
|||
#include "swift/extractor/infra/file/Path.h"
|
||||
#include "swift/extractor/infra/SwiftLocationExtractor.h"
|
||||
#include "swift/extractor/infra/SwiftBodyEmissionStrategy.h"
|
||||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
#include "swift/logging/SwiftAssert.h"
|
||||
|
||||
using namespace codeql;
|
||||
|
@ -49,24 +48,20 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: This should be factored out/replaced with simplified version of custom mangling
|
||||
static std::string mangledDeclName(const swift::ValueDecl& decl) {
|
||||
std::string_view moduleName = decl.getModuleContext()->getRealName().str();
|
||||
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
|
||||
if (decl.getKind() == swift::DeclKind::Module) {
|
||||
return std::string{moduleName};
|
||||
static std::string mangledDeclName(const swift::Decl& decl) {
|
||||
// SwiftRecursiveMangler mangled name cannot be used directly as it can be too long for file names
|
||||
// so we build some minimal human readable info for debuggability and append a hash
|
||||
auto ret = decl.getModuleContext()->getRealName().str().str();
|
||||
ret += '/';
|
||||
ret += swift::Decl::getKindName(decl.getKind());
|
||||
ret += '_';
|
||||
if (auto valueDecl = llvm::dyn_cast<swift::ValueDecl>(&decl); valueDecl && valueDecl->hasName()) {
|
||||
ret += valueDecl->getBaseName().userFacingName();
|
||||
ret += '_';
|
||||
}
|
||||
swift::Mangle::ASTMangler mangler;
|
||||
if (decl.getKind() == swift::DeclKind::TypeAlias) {
|
||||
// In cases like this (when coming from PCM)
|
||||
// typealias CFXMLTree = CFTree
|
||||
// typealias CFXMLTreeRef = CFXMLTree
|
||||
// mangleAnyDecl mangles both CFXMLTree and CFXMLTreeRef into 'So12CFXMLTreeRefa'
|
||||
// which is not correct and causes inconsistencies. mangleEntity makes these two distinct
|
||||
// prefix adds a couple of special symbols, we don't necessary need them
|
||||
return mangler.mangleEntity(&decl);
|
||||
}
|
||||
return mangler.mangleAnyDecl(&decl, /* prefix = */ false);
|
||||
SwiftRecursiveMangler mangler;
|
||||
ret += mangler.mangleDecl(decl).hash();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static fs::path getFilename(swift::ModuleDecl& module,
|
||||
|
@ -76,20 +71,7 @@ static fs::path getFilename(swift::ModuleDecl& module,
|
|||
return resolvePath(primaryFile->getFilename());
|
||||
}
|
||||
if (lazyDeclaration) {
|
||||
// this code will be thrown away in the near future
|
||||
auto decl = llvm::dyn_cast<swift::ValueDecl>(lazyDeclaration);
|
||||
CODEQL_ASSERT(decl, "not a ValueDecl");
|
||||
auto mangled = mangledDeclName(*decl);
|
||||
// mangled name can be too long to use as a file name, so we can't use it directly
|
||||
mangled = picosha2::hash256_hex_string(mangled);
|
||||
std::string ret;
|
||||
ret += module.getRealName().str();
|
||||
ret += '_';
|
||||
ret += decl->getBaseName().userFacingName();
|
||||
ret += '_';
|
||||
// half a SHA2 is enough
|
||||
ret += std::string_view(mangled).substr(0, mangled.size() / 2);
|
||||
return ret;
|
||||
return mangledDeclName(*lazyDeclaration);
|
||||
}
|
||||
// PCM clang module
|
||||
if (module.isNonSwiftModule()) {
|
||||
|
|
|
@ -11,5 +11,6 @@ swift_cc_library(
|
|||
"//swift/extractor/trap",
|
||||
"//swift/logging",
|
||||
"//swift/third_party/swift-llvm-support",
|
||||
"@picosha2",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -25,8 +25,8 @@ void SwiftLocationExtractor::attachLocationImpl(const swift::SourceManager& sour
|
|||
entry.file = fetchFileLabel(file);
|
||||
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
|
||||
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
|
||||
SwiftMangledName locName{{"loc", entry.file, ":", entry.start_line, ":", entry.start_column, ":",
|
||||
entry.end_line, ":", entry.end_column}};
|
||||
SwiftMangledName locName{"loc", entry.file, ':', entry.start_line, ':', entry.start_column,
|
||||
':', entry.end_line, ':', entry.end_column};
|
||||
entry.id = trap.createTypedLabel<DbLocationTag>(locName);
|
||||
trap.emit(entry);
|
||||
trap.emit(LocatableLocationsTrap{locatableLabel, entry.id});
|
||||
|
@ -99,7 +99,7 @@ TrapLabel<FileTag> SwiftLocationExtractor::fetchFileLabel(const std::filesystem:
|
|||
}
|
||||
|
||||
DbFile entry({});
|
||||
entry.id = trap.createTypedLabel<DbFileTag>({{"file_", file.string()}});
|
||||
entry.id = trap.createTypedLabel<DbFileTag>({"file_", file.string()});
|
||||
entry.name = file.string();
|
||||
trap.emit(entry);
|
||||
store[file] = entry.id;
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
#include <picosha2.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
namespace {
|
||||
void appendPart(std::string& out, const std::string& prefix) {
|
||||
out += prefix;
|
||||
std::string SwiftMangledName::hash() const {
|
||||
auto ret = picosha2::hash256_hex_string(value);
|
||||
// half a hash is already enough for disambuiguation
|
||||
ret.resize(ret.size() / 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void appendPart(std::string& out, UntypedTrapLabel label) {
|
||||
absl::StrAppend(&out, "{", label.str(), "}");
|
||||
SwiftMangledName& SwiftMangledName::operator<<(UntypedTrapLabel label) & {
|
||||
absl::StrAppend(&value, "{", label.str(), "}");
|
||||
return *this;
|
||||
}
|
||||
|
||||
void appendPart(std::string& out, unsigned index) {
|
||||
absl::StrAppend(&out, index);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string SwiftMangledName::str() const {
|
||||
std::string out;
|
||||
for (const auto& part : parts) {
|
||||
std::visit([&](const auto& contents) { appendPart(out, contents); }, part);
|
||||
}
|
||||
return out;
|
||||
SwiftMangledName& SwiftMangledName::operator<<(unsigned int i) & {
|
||||
absl::StrAppend(&value, i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
|
|
|
@ -9,37 +9,52 @@
|
|||
|
||||
namespace codeql {
|
||||
|
||||
struct SwiftMangledName {
|
||||
class SwiftMangledName {
|
||||
public:
|
||||
using Part = std::variant<UntypedTrapLabel, std::string, unsigned>;
|
||||
|
||||
std::vector<Part> parts;
|
||||
explicit operator bool() const { return !value.empty(); }
|
||||
|
||||
explicit operator bool() const { return !parts.empty(); }
|
||||
const std::string& str() const { return value; }
|
||||
operator std::string_view() const { return value; }
|
||||
|
||||
std::string str() const;
|
||||
std::string hash() const;
|
||||
|
||||
// streaming labels or ints into a SwiftMangledName just appends them
|
||||
template <typename Tag>
|
||||
SwiftMangledName& operator<<(TrapLabel<Tag> label) {
|
||||
parts.emplace_back(label);
|
||||
return *this;
|
||||
// let's avoid copying as long as we don't need it
|
||||
SwiftMangledName() = default;
|
||||
SwiftMangledName(const SwiftMangledName&) = delete;
|
||||
SwiftMangledName& operator=(const SwiftMangledName&) = delete;
|
||||
SwiftMangledName(SwiftMangledName&&) = default;
|
||||
SwiftMangledName& operator=(SwiftMangledName&&) = default;
|
||||
|
||||
template <typename... Args>
|
||||
SwiftMangledName(Args&&... args) {
|
||||
(operator<<(std::forward<Args>(args)), ...);
|
||||
}
|
||||
|
||||
SwiftMangledName& operator<<(unsigned i) {
|
||||
parts.emplace_back(i);
|
||||
return *this;
|
||||
SwiftMangledName& operator<<(UntypedTrapLabel label) &;
|
||||
SwiftMangledName& operator<<(unsigned i) &;
|
||||
|
||||
template <typename Tag>
|
||||
SwiftMangledName& operator<<(TrapLabel<Tag> label) & {
|
||||
return operator<<(static_cast<UntypedTrapLabel>(label));
|
||||
}
|
||||
|
||||
// streaming string-like stuff will add a new part it only if strictly required, otherwise it will
|
||||
// append to the last part if it is a string
|
||||
template <typename T>
|
||||
SwiftMangledName& operator<<(T&& arg) {
|
||||
if (parts.empty() || !std::holds_alternative<std::string>(parts.back())) {
|
||||
parts.emplace_back("");
|
||||
}
|
||||
std::get<std::string>(parts.back()) += std::forward<T>(arg);
|
||||
SwiftMangledName& operator<<(T&& arg) & {
|
||||
value += arg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SwiftMangledName&& operator<<(T&& arg) && {
|
||||
return std::move(operator<<(std::forward<T>(arg)));
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
|
|
@ -1,89 +1,403 @@
|
|||
#include "swift/extractor/mangler/SwiftMangler.h"
|
||||
#include "swift/extractor/infra/SwiftDispatcher.h"
|
||||
#include "swift/extractor/trap/generated/decl/TrapClasses.h"
|
||||
#include "swift/logging/SwiftLogging.h"
|
||||
|
||||
#include <swift/AST/Module.h>
|
||||
#include <swift/AST/ParameterList.h>
|
||||
#include <swift/AST/ASTContext.h>
|
||||
#include <swift/AST/GenericParamList.h>
|
||||
#include <sstream>
|
||||
|
||||
using namespace codeql;
|
||||
|
||||
namespace {
|
||||
SwiftMangledName initMangled(const swift::TypeBase* type) {
|
||||
Logger& logger() {
|
||||
static Logger ret{"mangler"};
|
||||
return ret;
|
||||
}
|
||||
|
||||
const swift::Decl* getParent(const swift::Decl* decl) {
|
||||
auto context = decl->getDeclContext();
|
||||
if (context->getContextKind() == swift::DeclContextKind::FileUnit) {
|
||||
return decl->getModuleContext();
|
||||
}
|
||||
return context->getAsDecl();
|
||||
}
|
||||
|
||||
std::string_view getTypeKindStr(const swift::TypeBase* type) {
|
||||
switch (type->getKind()) {
|
||||
#define TYPE(ID, PARENT) \
|
||||
case swift::TypeKind::ID: \
|
||||
return {{#ID "Type_"}};
|
||||
return #ID "Type";
|
||||
#include <swift/AST/TypeNodes.def>
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
SwiftMangledName initMangled(const swift::Decl* decl) {
|
||||
SwiftMangledName ret;
|
||||
ret << swift::Decl::getKindName(decl->getKind()) << "Decl_";
|
||||
return ret;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SwiftMangledName SwiftMangler::initMangled(const swift::TypeBase* type) {
|
||||
return {getTypeKindStr(type), '_'};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::initMangled(const swift::Decl* decl) {
|
||||
return {swift::Decl::getKindName(decl->getKind()), "Decl_", fetch(getParent(decl))};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::mangleModuleName(std::string_view name) {
|
||||
SwiftMangledName ret = {{"ModuleDecl_"}};
|
||||
ret << name;
|
||||
return ret;
|
||||
return {"ModuleDecl_", name};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::mangleDecl(const swift::Decl& decl) {
|
||||
if (!llvm::isa<swift::ValueDecl>(decl)) {
|
||||
return {};
|
||||
}
|
||||
// We do not deduplicate local variables, but for the moment also non-local vars from non-swift
|
||||
// (PCM, clang modules) modules as the mangler crashes sometimes
|
||||
if (decl.getKind() == swift::DeclKind::Var &&
|
||||
(decl.getDeclContext()->isLocalContext() || decl.getModuleContext()->isNonSwiftModule())) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// we do not deduplicate GenericTypeParamDecl, as their mangling is ambiguous in the presence of
|
||||
// extensions
|
||||
if (decl.getKind() == swift::DeclKind::GenericTypeParam) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (decl.getKind() == swift::DeclKind::Module) {
|
||||
return mangleModuleName(llvm::cast<swift::ModuleDecl>(decl).getRealName().str());
|
||||
}
|
||||
|
||||
auto ret = initMangled(&decl);
|
||||
const auto& valueDecl = llvm::cast<swift::ValueDecl>(decl);
|
||||
// stamp all declarations with an id-ref of the containing module
|
||||
auto moduleLabel = dispatcher.fetchLabel(decl.getModuleContext());
|
||||
ret << moduleLabel;
|
||||
if (decl.getKind() == swift::DeclKind::TypeAlias) {
|
||||
// In cases like this (when coming from PCM)
|
||||
// typealias CFXMLTree = CFTree
|
||||
// typealias CFXMLTreeRef = CFXMLTree
|
||||
// mangleAnyDecl mangles both CFXMLTree and CFXMLTreeRef into 'So12CFXMLTreeRefa'
|
||||
// which is not correct and causes inconsistencies. mangleEntity makes these two distinct
|
||||
// prefix adds a couple of special symbols, we don't necessary need them
|
||||
ret << mangler.mangleEntity(&valueDecl);
|
||||
} else {
|
||||
// prefix adds a couple of special symbols, we don't necessary need them
|
||||
ret << mangler.mangleAnyDecl(&valueDecl, /* prefix = */ false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitModuleType(const swift::ModuleType* type) {
|
||||
auto ret = initMangled(type);
|
||||
ret << type->getModule()->getRealName().str();
|
||||
if (type->getModule()->isNonSwiftModule()) {
|
||||
SwiftMangledName SwiftMangler::visitModuleDecl(const swift::ModuleDecl* decl) {
|
||||
auto ret = mangleModuleName(decl->getRealName().str());
|
||||
if (decl->isNonSwiftModule()) {
|
||||
ret << "|clang";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitBuiltinType(const swift::BuiltinType* type) {
|
||||
auto ret = initMangled(type);
|
||||
llvm::SmallString<32> buffer;
|
||||
ret << type->getTypeName(buffer, /* prependBuiltinNamespace= */ false);
|
||||
SwiftMangledName SwiftMangler::visitValueDecl(const swift::ValueDecl* decl, bool force) {
|
||||
if (!force && (!decl->hasName() || decl->getDeclContext()->isLocalContext())) {
|
||||
return {};
|
||||
}
|
||||
auto ret = initMangled(decl);
|
||||
std::string name;
|
||||
llvm::raw_string_ostream oss{name};
|
||||
decl->getName().print(oss);
|
||||
ret << name;
|
||||
if (decl->isStatic()) {
|
||||
ret << "|static";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitTypeDiscriminatedValueDecl(const swift::ValueDecl* decl) {
|
||||
if (auto ret = visitValueDecl(decl)) {
|
||||
ret << fetch(decl->getInterfaceType()->getCanonicalType());
|
||||
return ret;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitAbstractFunctionDecl(const swift::AbstractFunctionDecl* decl) {
|
||||
return visitTypeDiscriminatedValueDecl(decl);
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitSubscriptDecl(const swift::SubscriptDecl* decl) {
|
||||
return visitTypeDiscriminatedValueDecl(decl);
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitVarDecl(const swift::VarDecl* decl) {
|
||||
return visitTypeDiscriminatedValueDecl(decl);
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitExtensionDecl(const swift::ExtensionDecl* decl) {
|
||||
if (decl->getDeclContext()->isLocalContext()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto parent = getParent(decl);
|
||||
return initMangled(decl) << fetch(parent) << getExtensionIndex(decl, parent);
|
||||
}
|
||||
|
||||
unsigned SwiftMangler::getExtensionIndex(const swift::ExtensionDecl* decl,
|
||||
const swift::Decl* parent) {
|
||||
// to avoid iterating multiple times on the parent of multiple extensions, we preload extension
|
||||
// indexes once for each encountered parent into the `preloadedExtensionIndexes` mapping.
|
||||
// Because we mangle declarations only once in a given trap/dispatcher context, we can safely
|
||||
// discard preloaded indexes on use
|
||||
if (auto found = preloadedExtensionIndexes.extract(decl)) {
|
||||
return found.mapped();
|
||||
}
|
||||
if (auto parentModule = llvm::dyn_cast<swift::ModuleDecl>(parent)) {
|
||||
llvm::SmallVector<swift::Decl*> siblings;
|
||||
parentModule->getTopLevelDecls(siblings);
|
||||
indexExtensions(siblings);
|
||||
} else if (auto iterableParent = llvm::dyn_cast<swift::IterableDeclContext>(parent)) {
|
||||
indexExtensions(iterableParent->getAllMembers());
|
||||
} else {
|
||||
// TODO use a generic logging handle for Swift entities here, once it's available
|
||||
CODEQL_ASSERT(false, "non-local context must be module or iterable decl context");
|
||||
}
|
||||
auto found = preloadedExtensionIndexes.extract(decl);
|
||||
// TODO use a generic logging handle for Swift entities here, once it's available
|
||||
CODEQL_ASSERT(found, "extension not found within parent");
|
||||
return found.mapped();
|
||||
}
|
||||
|
||||
void SwiftMangler::indexExtensions(llvm::ArrayRef<swift::Decl*> siblings) {
|
||||
auto index = 0u;
|
||||
for (auto sibling : siblings) {
|
||||
if (sibling->getKind() == swift::DeclKind::Extension) {
|
||||
preloadedExtensionIndexes.emplace(sibling, index);
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitGenericTypeParamDecl(const swift::GenericTypeParamDecl* decl) {
|
||||
return visitValueDecl(decl, /*force=*/true) << '_' << decl->getDepth() << '_' << decl->getIndex();
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitAssociatedTypeDecl(const swift::AssociatedTypeDecl* decl) {
|
||||
return visitValueDecl(decl, /*force=*/true);
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitModuleType(const swift::ModuleType* type) {
|
||||
return initMangled(type) << fetch(type->getModule());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitTupleType(const swift::TupleType* type) {
|
||||
auto ret = initMangled(type);
|
||||
for (const auto& element : type->getElements()) {
|
||||
if (element.hasName()) {
|
||||
ret << element.getName().str();
|
||||
}
|
||||
ret << fetch(element.getType());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitBuiltinType(const swift::BuiltinType* type) {
|
||||
llvm::SmallString<32> buffer;
|
||||
return initMangled(type) << type->getTypeName(buffer, /* prependBuiltinNamespace= */ false);
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitAnyGenericType(const swift::AnyGenericType* type) {
|
||||
auto ret = initMangled(type);
|
||||
auto decl = type->getDecl();
|
||||
ret << fetch(decl);
|
||||
if (auto parent = type->getParent()) {
|
||||
ret << fetch(parent);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitType(const swift::TypeBase* type) {
|
||||
LOG_WARNING("encountered {} for which we give no name", getTypeKindStr(type));
|
||||
return {};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitBoundGenericType(const swift::BoundGenericType* type) {
|
||||
auto ret = visitAnyGenericType(type);
|
||||
for (const auto param : type->getGenericArgs()) {
|
||||
ret << fetch(param);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitAnyFunctionType(const swift::AnyFunctionType* type) {
|
||||
auto ret = initMangled(type);
|
||||
for (const auto& param : type->getParams()) {
|
||||
ret << fetch(param.getPlainType());
|
||||
if (param.isInOut()) {
|
||||
ret << "_inout";
|
||||
}
|
||||
if (param.isOwned()) {
|
||||
ret << "_owned";
|
||||
}
|
||||
if (param.isShared()) {
|
||||
ret << "_shared";
|
||||
}
|
||||
if (param.isIsolated()) {
|
||||
ret << "_isolated";
|
||||
}
|
||||
if (param.isVariadic()) {
|
||||
ret << "...";
|
||||
}
|
||||
}
|
||||
ret << "->" << fetch(type->getResult());
|
||||
if (type->isAsync()) {
|
||||
ret << "_async";
|
||||
}
|
||||
if (type->isThrowing()) {
|
||||
ret << "_throws";
|
||||
}
|
||||
if (type->isSendable()) {
|
||||
ret << "_sendable";
|
||||
}
|
||||
if (type->isNoEscape()) {
|
||||
ret << "_noescape";
|
||||
}
|
||||
if (type->hasGlobalActor()) {
|
||||
ret << "_actor" << fetch(type->getGlobalActor());
|
||||
}
|
||||
// TODO: see if this needs to be used in identifying types, if not it needs to be removed from
|
||||
// type printing in the Swift compiler code
|
||||
assert(type->hasExtInfo() && "type must have ext info");
|
||||
auto info = type->getExtInfo();
|
||||
auto convention = info.getSILRepresentation();
|
||||
if (convention != swift::SILFunctionTypeRepresentation::Thick) {
|
||||
ret << "_convention" << static_cast<unsigned>(convention);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitGenericFunctionType(const swift::GenericFunctionType* type) {
|
||||
auto ret = visitAnyFunctionType(type);
|
||||
ret << '<';
|
||||
for (auto paramType : type->getGenericParams()) {
|
||||
ret << fetch(paramType);
|
||||
}
|
||||
ret << '>';
|
||||
if (!type->getRequirements().empty()) {
|
||||
ret << "where_";
|
||||
for (const auto& req : type->getRequirements()) {
|
||||
ret << fetch(req.getFirstType().getPointer());
|
||||
ret << (req.getKind() == swift::RequirementKind::SameType ? '=' : ':');
|
||||
if (req.getKind() == swift::RequirementKind::Layout) {
|
||||
ret << '(' << req.getLayoutConstraint().getString() << ')';
|
||||
} else {
|
||||
ret << fetch(req.getSecondType());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitGenericTypeParamType(const swift::GenericTypeParamType* type) {
|
||||
auto ret = initMangled(type);
|
||||
if (auto decl = type->getDecl()) {
|
||||
ret << fetch(decl);
|
||||
} else {
|
||||
// type parameter is canonicalized to a depth/index coordinate
|
||||
ret << type->getDepth() << '_' << type->getIndex();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitAnyMetatypeType(const swift::AnyMetatypeType* type) {
|
||||
return initMangled(type) << fetch(type->getInstanceType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitDependentMemberType(const swift::DependentMemberType* type) {
|
||||
return initMangled(type) << fetch(type->getBase()) << fetch(type->getAssocType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitInOutType(const swift::InOutType* type) {
|
||||
return initMangled(type) << fetch(type->getObjectType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitExistentialType(const swift::ExistentialType* type) {
|
||||
return initMangled(type) << fetch(type->getConstraintType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitUnarySyntaxSugarType(const swift::UnarySyntaxSugarType* type) {
|
||||
return initMangled(type) << fetch(type->getBaseType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitDictionaryType(const swift::DictionaryType* type) {
|
||||
return initMangled(type) << fetch(type->getKeyType()) << fetch(type->getValueType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitTypeAliasType(const swift::TypeAliasType* type) {
|
||||
auto ret = initMangled(type);
|
||||
ret << fetch(type->getDecl());
|
||||
if (auto parent = type->getParent()) {
|
||||
ret << fetch(parent);
|
||||
}
|
||||
ret << '<';
|
||||
for (auto replacement : type->getSubstitutionMap().getReplacementTypes()) {
|
||||
ret << fetch(replacement);
|
||||
}
|
||||
ret << '>';
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitArchetypeType(const swift::ArchetypeType* type) {
|
||||
auto ret = initMangled(type) << fetch(type->getInterfaceType());
|
||||
if (const auto super = type->getSuperclass()) {
|
||||
ret << ':' << fetch(super);
|
||||
}
|
||||
for (const auto* protocol : type->getConformsTo()) {
|
||||
// Including the protocols in the mangled name allows us to distinguish the "same" type in
|
||||
// different extensions, where it might have different constraints. Mangling the context (i.e.
|
||||
// which ExtensionDecl or ValueDecl it's mentioned in) might be more robust, but there doesn't
|
||||
// seem to be a clean way to get it.
|
||||
ret << ':' << fetch(protocol);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitOpaqueTypeArchetypeType(
|
||||
const swift::OpaqueTypeArchetypeType* type) {
|
||||
return visitArchetypeType(type) << fetch(type->getDecl());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitOpenedArchetypeType(const swift::OpenedArchetypeType* type) {
|
||||
llvm::SmallVector<char> uuid;
|
||||
type->getOpenedExistentialID().toString(uuid);
|
||||
return visitArchetypeType(type) << std::string_view(uuid.data(), uuid.size());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitProtocolCompositionType(
|
||||
const swift::ProtocolCompositionType* type) {
|
||||
auto ret = initMangled(type);
|
||||
for (auto composed : type->getMembers()) {
|
||||
ret << fetch(composed);
|
||||
}
|
||||
if (type->hasExplicitAnyObject()) {
|
||||
ret << "&AnyObject";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitParenType(const swift::ParenType* type) {
|
||||
return initMangled(type) << fetch(type->getUnderlyingType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitLValueType(const swift::LValueType* type) {
|
||||
return initMangled(type) << fetch(type->getObjectType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitDynamicSelfType(const swift::DynamicSelfType* type) {
|
||||
return initMangled(type) << fetch(type->getSelfType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitUnboundGenericType(const swift::UnboundGenericType* type) {
|
||||
return initMangled(type) << fetch(type->getDecl());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitReferenceStorageType(const swift::ReferenceStorageType* type) {
|
||||
return initMangled(type) << fetch(type->getReferentType());
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftMangler::visitParametrizedProtocolType(
|
||||
const swift::ParameterizedProtocolType* type) {
|
||||
auto ret = initMangled(type);
|
||||
ret << fetch(type->getBaseType());
|
||||
ret << '<';
|
||||
for (auto arg : type->getArgs()) {
|
||||
ret << fetch(arg);
|
||||
}
|
||||
ret << '>';
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename E>
|
||||
UntypedTrapLabel fetchLabel(SwiftDispatcher& dispatcher, const E* e) {
|
||||
auto ret = dispatcher.fetchLabel(e);
|
||||
// TODO use a generic logging handle for Swift entities here, once it's available
|
||||
CODEQL_ASSERT(ret.valid(), "using an undefined label in mangling");
|
||||
return ret;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SwiftMangledName SwiftTrapMangler::fetch(const swift::Decl* decl) {
|
||||
return {fetchLabel(dispatcher, decl)};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftTrapMangler::fetch(const swift::TypeBase* type) {
|
||||
return {fetchLabel(dispatcher, type)};
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftRecursiveMangler::fetch(const swift::Decl* decl) {
|
||||
return mangleDecl(*decl).hash();
|
||||
}
|
||||
|
||||
SwiftMangledName SwiftRecursiveMangler::fetch(const swift::TypeBase* type) {
|
||||
return mangleType(*type).hash();
|
||||
}
|
||||
|
|
|
@ -11,39 +11,132 @@
|
|||
#include "swift/extractor/infra/SwiftMangledName.h"
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class SwiftDispatcher;
|
||||
|
||||
class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName> {
|
||||
// This class is tasked with assigning unique names to entities that need it (non-local
|
||||
// declarations and types), to be used as trap keys.
|
||||
// This uses the Template Method design pattern (or Non-Virtual Interface). The actual behavior
|
||||
// when the identity depends on some other entity (like the parent of a declaration, or the
|
||||
// declaration introducing a user type) depends on a private virtual fetch method. See below for
|
||||
// the specific implementations.
|
||||
//
|
||||
// * all names are prefixed with the name of the entity class (for example `ParamDecl_`)
|
||||
// * declarations usually use a fetch of their declaration context as first element, followed
|
||||
// by whatever distinguishes them within that context (the name, or the signature for function)
|
||||
// * user defined types have a name that is a simple wrapper around a fetch of their declaration
|
||||
class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
|
||||
private swift::DeclVisitor<SwiftMangler, SwiftMangledName> {
|
||||
using TypeVisitor = swift::TypeVisitor<SwiftMangler, SwiftMangledName>;
|
||||
using DeclVisitor = swift::DeclVisitor<SwiftMangler, SwiftMangledName>;
|
||||
|
||||
public:
|
||||
explicit SwiftMangler(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
virtual ~SwiftMangler() = default;
|
||||
|
||||
static SwiftMangledName mangleModuleName(std::string_view name);
|
||||
|
||||
// TODO actual visit
|
||||
SwiftMangledName mangleDecl(const swift::Decl& decl);
|
||||
SwiftMangledName mangleDecl(const swift::Decl& decl) {
|
||||
return DeclVisitor::visit(const_cast<swift::Decl*>(&decl));
|
||||
}
|
||||
|
||||
SwiftMangledName mangleType(const swift::TypeBase& type) {
|
||||
return visit(const_cast<swift::TypeBase*>(&type));
|
||||
return TypeVisitor::visit(const_cast<swift::TypeBase*>(&type));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class swift::TypeVisitor<SwiftMangler, SwiftMangledName>;
|
||||
friend TypeVisitor;
|
||||
friend DeclVisitor;
|
||||
|
||||
// default fallback for not yet mangled types. This should never be called in normal situations
|
||||
// will just spawn a random name
|
||||
// TODO: make it assert once we mangle all types
|
||||
static SwiftMangledName visitType(const swift::TypeBase* type) { return {}; }
|
||||
// assign no name by default
|
||||
static SwiftMangledName visitDecl(const swift::Decl* decl) { return {}; }
|
||||
|
||||
// current default, falling back to internal mangling
|
||||
SwiftMangledName visitValueDecl(const swift::ValueDecl* decl, bool force = false);
|
||||
|
||||
SwiftMangledName visitModuleDecl(const swift::ModuleDecl* decl);
|
||||
SwiftMangledName visitExtensionDecl(const swift::ExtensionDecl* decl);
|
||||
SwiftMangledName visitAbstractFunctionDecl(const swift::AbstractFunctionDecl* decl);
|
||||
SwiftMangledName visitSubscriptDecl(const swift::SubscriptDecl* decl);
|
||||
SwiftMangledName visitVarDecl(const swift::VarDecl* decl);
|
||||
SwiftMangledName visitGenericTypeParamDecl(const swift::GenericTypeParamDecl* decl);
|
||||
SwiftMangledName visitAssociatedTypeDecl(const swift::AssociatedTypeDecl* decl);
|
||||
|
||||
// default fallback for non mangled types. This covers types that should not appear in normal
|
||||
// successful extractor runs, like ErrorType
|
||||
SwiftMangledName visitType(const swift::TypeBase* type);
|
||||
|
||||
SwiftMangledName visitModuleType(const swift::ModuleType* type);
|
||||
|
||||
SwiftMangledName visitTupleType(const swift::TupleType* type);
|
||||
SwiftMangledName visitBuiltinType(const swift::BuiltinType* type);
|
||||
SwiftMangledName visitAnyGenericType(const swift::AnyGenericType* type);
|
||||
|
||||
// shouldn't be required, but they forgot to link `NominalType` to its direct superclass
|
||||
// in swift/AST/TypeNodes.def, so we need to chain the call manually
|
||||
SwiftMangledName visitNominalType(const swift::NominalType* type) {
|
||||
return visitAnyGenericType(type);
|
||||
}
|
||||
|
||||
SwiftMangledName visitBoundGenericType(const swift::BoundGenericType* type);
|
||||
SwiftMangledName visitAnyFunctionType(const swift::AnyFunctionType* type);
|
||||
SwiftMangledName visitGenericFunctionType(const swift::GenericFunctionType* type);
|
||||
SwiftMangledName visitGenericTypeParamType(const swift::GenericTypeParamType* type);
|
||||
SwiftMangledName visitAnyMetatypeType(const swift::AnyMetatypeType* type);
|
||||
SwiftMangledName visitDependentMemberType(const swift::DependentMemberType* type);
|
||||
SwiftMangledName visitInOutType(const swift::InOutType* type);
|
||||
SwiftMangledName visitExistentialType(const swift::ExistentialType* type);
|
||||
SwiftMangledName visitUnarySyntaxSugarType(const swift::UnarySyntaxSugarType* type);
|
||||
SwiftMangledName visitDictionaryType(const swift::DictionaryType* type);
|
||||
SwiftMangledName visitTypeAliasType(const swift::TypeAliasType* type);
|
||||
SwiftMangledName visitArchetypeType(const swift::ArchetypeType* type);
|
||||
SwiftMangledName visitOpaqueTypeArchetypeType(const swift::OpaqueTypeArchetypeType* type);
|
||||
SwiftMangledName visitOpenedArchetypeType(const swift::OpenedArchetypeType* type);
|
||||
SwiftMangledName visitProtocolCompositionType(const swift::ProtocolCompositionType* type);
|
||||
SwiftMangledName visitParenType(const swift::ParenType* type);
|
||||
SwiftMangledName visitLValueType(const swift::LValueType* type);
|
||||
SwiftMangledName visitDynamicSelfType(const swift::DynamicSelfType* type);
|
||||
SwiftMangledName visitUnboundGenericType(const swift::UnboundGenericType* type);
|
||||
SwiftMangledName visitReferenceStorageType(const swift::ReferenceStorageType* type);
|
||||
SwiftMangledName visitParametrizedProtocolType(const swift::ParameterizedProtocolType* type);
|
||||
|
||||
private:
|
||||
swift::Mangle::ASTMangler mangler;
|
||||
std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;
|
||||
|
||||
virtual SwiftMangledName fetch(const swift::Decl* decl) = 0;
|
||||
virtual SwiftMangledName fetch(const swift::TypeBase* type) = 0;
|
||||
SwiftMangledName fetch(swift::Type type) { return fetch(type.getPointer()); }
|
||||
|
||||
void indexExtensions(llvm::ArrayRef<swift::Decl*> siblings);
|
||||
unsigned int getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
|
||||
static SwiftMangledName initMangled(const swift::TypeBase* type);
|
||||
SwiftMangledName initMangled(const swift::Decl* decl);
|
||||
SwiftMangledName visitTypeDiscriminatedValueDecl(const swift::ValueDecl* decl);
|
||||
};
|
||||
|
||||
// This implementation is indented for use in defining trap keys. In this case fetching gives
|
||||
// a [trap id-ref][1] is used, using the dispatcher to give us a label reference to that entity.
|
||||
// Because that entity will also generally have a mangled name, it is important that this does not
|
||||
// lead to any recursive loop (which is checked at runtime within the dispatcher).
|
||||
//
|
||||
// [1]: https://github.com/github/codeql-core/blob/main/wiki/extractors/trap.md#ids
|
||||
class SwiftTrapMangler : public SwiftMangler {
|
||||
public:
|
||||
explicit SwiftTrapMangler(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
private:
|
||||
SwiftMangledName fetch(const swift::Decl* decl) override;
|
||||
SwiftMangledName fetch(const swift::TypeBase* type) override;
|
||||
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
// In this implementation, fetching gives a hash of the mangled name itself, leading to a direct
|
||||
// recursion. This is intended for use in trap file names.
|
||||
class SwiftRecursiveMangler : public SwiftMangler {
|
||||
SwiftMangledName fetch(const swift::Decl* decl) override;
|
||||
SwiftMangledName fetch(const swift::TypeBase* type) override;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
|
|
@ -58,7 +58,7 @@ class SwiftVisitor : private SwiftDispatcher {
|
|||
StmtTranslator stmtTranslator{*this};
|
||||
TypeTranslator typeTranslator{*this};
|
||||
PatternTranslator patternTranslator{*this};
|
||||
SwiftMangler mangler{*this};
|
||||
SwiftTrapMangler mangler{*this};
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
|
|
|
@ -40,6 +40,7 @@ class UntypedTrapLabel {
|
|||
}
|
||||
|
||||
std::string str() const {
|
||||
assert(valid() && "outputting an undefined label!");
|
||||
std::string ret(strSize(), '\0');
|
||||
ret[0] = '#';
|
||||
std::to_chars(ret.data() + 1, ret.data() + ret.size(), id_, 16);
|
||||
|
|
|
@ -1,16 +1,93 @@
|
|||
| Sources/deduplication/def.swift:1:1:1:9 | var ... = ... | PatternBindingDecl |
|
||||
| Sources/deduplication/def.swift:1:5:1:5 | x | ConcreteVarDecl |
|
||||
| Sources/deduplication/def.swift:3:1:3:20 | Generic | StructDecl |
|
||||
| Sources/deduplication/def.swift:3:8:3:8 | Generic<T>.init() | Initializer |
|
||||
| Sources/deduplication/def.swift:3:8:3:8 | self | ParamDecl |
|
||||
| Sources/deduplication/def.swift:3:16:3:16 | T | GenericTypeParamDecl |
|
||||
| Sources/deduplication/def.swift:5:1:5:41 | var ... = ... | PatternBindingDecl |
|
||||
| Sources/deduplication/def.swift:5:5:5:5 | instantiated_generic | ConcreteVarDecl |
|
||||
| Sources/deduplication/def.swift:7:1:7:42 | function(_:) | NamedFunction |
|
||||
| Sources/deduplication/def.swift:7:15:7:18 | _ | ParamDecl |
|
||||
| Sources/deduplication/use.swift:1:1:1:13 | var ... = ... | PatternBindingDecl |
|
||||
| Sources/deduplication/use.swift:1:5:1:5 | use_x | ConcreteVarDecl |
|
||||
| Sources/deduplication/use.swift:2:1:2:32 | var ... = ... | PatternBindingDecl |
|
||||
| Sources/deduplication/use.swift:2:5:2:5 | use_instantiated_generic | ConcreteVarDecl |
|
||||
| Sources/deduplication/use.swift:3:1:3:20 | var ... = ... | PatternBindingDecl |
|
||||
| Sources/deduplication/use.swift:3:5:3:5 | use_function | ConcreteVarDecl |
|
||||
| Sources/deduplication/def.swift:1:1:1:15 | var ... = ... | PatternBindingDecl | - |
|
||||
| Sources/deduplication/def.swift:1:5:1:5 | def_int | ConcreteVarDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:3:1:5:1 | Generic | StructDecl | Generic<T>.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:3:8:3:8 | Generic<T>.init() | Initializer | <T> (Generic<T>.Type) -> () -> Generic<T> [GenericFunctionType] |
|
||||
| Sources/deduplication/def.swift:3:8:3:8 | self | ParamDecl | Generic<T> [BoundGenericStructType] |
|
||||
| Sources/deduplication/def.swift:3:16:3:16 | T | GenericTypeParamDecl | T.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:4:5:4:70 | def_generic_method(t:u:v:) | NamedFunction | <T, U, V> (Generic<T>) -> (T, U, V) -> T [GenericFunctionType] |
|
||||
| Sources/deduplication/def.swift:4:10:4:10 | self | ParamDecl | Generic<T> [BoundGenericStructType] |
|
||||
| Sources/deduplication/def.swift:4:29:4:29 | U | GenericTypeParamDecl | U.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:4:32:4:32 | V | GenericTypeParamDecl | V.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:4:35:4:38 | t | ParamDecl | T [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:4:41:4:44 | u | ParamDecl | U [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:4:47:4:50 | v | ParamDecl | V [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:7:1:7:45 | var ... = ... | PatternBindingDecl | - |
|
||||
| Sources/deduplication/def.swift:7:5:7:5 | def_instantiated_generic | ConcreteVarDecl | Generic<Int> [BoundGenericStructType] |
|
||||
| Sources/deduplication/def.swift:9:1:9:46 | def_function(_:) | NamedFunction | (Int) -> Int [FunctionType] |
|
||||
| Sources/deduplication/def.swift:9:19:9:22 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:11:1:11:77 | def_function_overloaded_on_return(_:_:) | NamedFunction | (Int, Double) -> Int [FunctionType] |
|
||||
| Sources/deduplication/def.swift:11:40:11:43 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:11:48:11:51 | _ | ParamDecl | Double [StructType] |
|
||||
| Sources/deduplication/def.swift:12:1:12:82 | def_function_overloaded_on_return(_:_:) | NamedFunction | (Int, Double) -> Double [FunctionType] |
|
||||
| Sources/deduplication/def.swift:12:40:12:43 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:12:48:12:51 | _ | ParamDecl | Double [StructType] |
|
||||
| Sources/deduplication/def.swift:14:1:14:57 | def_function_overloaded_on_parameter_type(_:) | NamedFunction | (Int) -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:14:48:14:51 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:15:1:15:60 | def_function_overloaded_on_parameter_type(_:) | NamedFunction | (Double) -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:15:48:15:51 | _ | ParamDecl | Double [StructType] |
|
||||
| Sources/deduplication/def.swift:17:1:17:62 | def_function_overloaded_on_parameter_label(one:) | NamedFunction | (Int) -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:17:49:17:56 | x | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:18:1:18:62 | def_function_overloaded_on_parameter_label(two:) | NamedFunction | (Int) -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:18:49:18:56 | x | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:20:1:20:44 | def_throwing_function(_:) | NamedFunction | (Int) throws -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:20:28:20:31 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:21:1:21:60 | def_rethrowing_function(_:) | NamedFunction | (() throws -> ()) throws -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:21:30:21:47 | _ | ParamDecl | () throws -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:22:1:22:40 | def_async_function(_:) | NamedFunction | (Int) async -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:22:25:22:28 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:23:1:23:56 | def_async_throwing_function(_:) | NamedFunction | (Int) async throws -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:23:34:23:37 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/def.swift:24:1:24:72 | def_async_rethrowing_function(_:) | NamedFunction | (() throws -> ()) async throws -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:24:36:24:53 | _ | ParamDecl | () throws -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:26:1:26:55 | def_generic_function(_:_:_:) | NamedFunction | <A, B, C> (A, B, C) -> () [GenericFunctionType] |
|
||||
| Sources/deduplication/def.swift:26:27:26:27 | A | GenericTypeParamDecl | A.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:26:30:26:30 | B | GenericTypeParamDecl | B.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:26:33:26:33 | C | GenericTypeParamDecl | C.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:26:36:26:39 | _ | ParamDecl | A [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:26:42:26:45 | _ | ParamDecl | B [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:26:48:26:51 | _ | ParamDecl | C [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:28:1:28:21 | Protocol1 | ProtocolDecl | Protocol1.Protocol [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:29:1:31:1 | Protocol2 | ProtocolDecl | Protocol2.Protocol [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:30:5:30:20 | Associated | AssociatedTypeDecl | Self.Associated.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:32:1:32:14 | Class | ClassDecl | Class.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:32:7:32:7 | Class.deinit() | Deinitializer | (Class) -> () -> () [FunctionType] |
|
||||
| Sources/deduplication/def.swift:32:7:32:7 | Class.init() | Initializer | (Class.Type) -> () -> Class [FunctionType] |
|
||||
| Sources/deduplication/def.swift:32:7:32:7 | self | ParamDecl | Class [ClassType] |
|
||||
| Sources/deduplication/def.swift:32:7:32:7 | self | ParamDecl | Class [ClassType] |
|
||||
| Sources/deduplication/def.swift:34:1:34:128 | def_generic_function_with_conformance(_:_:_:) | NamedFunction | <A, B, C where A : Protocol1, A : Protocol2, B : Class, C == A.Associated> (A, B, C) -> () [GenericFunctionType] |
|
||||
| Sources/deduplication/def.swift:34:44:34:60 | A | GenericTypeParamDecl | A.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:34:71:34:75 | B | GenericTypeParamDecl | B.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:34:82:34:82 | C | GenericTypeParamDecl | C.Type [MetatypeType] |
|
||||
| Sources/deduplication/def.swift:34:85:34:88 | _ | ParamDecl | A [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:34:91:34:94 | _ | ParamDecl | B [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:34:97:34:100 | _ | ParamDecl | C [GenericTypeParamType] |
|
||||
| Sources/deduplication/def.swift:36:1:36:18 | extension of Class | ExtensionDecl | - |
|
||||
| Sources/deduplication/use.swift:1:1:1:15 | var ... = ... | PatternBindingDecl | - |
|
||||
| Sources/deduplication/use.swift:1:5:1:5 | use_int | ConcreteVarDecl | Int [StructType] |
|
||||
| Sources/deduplication/use.swift:2:1:2:32 | var ... = ... | PatternBindingDecl | - |
|
||||
| Sources/deduplication/use.swift:2:5:2:5 | use_instantiated_generic | ConcreteVarDecl | Generic<Int> [BoundGenericStructType] |
|
||||
| Sources/deduplication/use.swift:3:1:3:83 | var ... = ... | PatternBindingDecl | - |
|
||||
| Sources/deduplication/use.swift:3:5:3:5 | answer | ConcreteVarDecl | Int [StructType] |
|
||||
| Sources/deduplication/use.swift:4:1:4:20 | var ... = ... | PatternBindingDecl | - |
|
||||
| Sources/deduplication/use.swift:4:5:4:5 | use_function | ConcreteVarDecl | (Int) -> Int [FunctionType] |
|
||||
| Sources/deduplication/use.swift:5:1:5:66 | use_generic_function_type(_:_:_:) | NamedFunction | <AA, BB, CC> (AA, BB, CC) -> () [GenericFunctionType] |
|
||||
| Sources/deduplication/use.swift:5:32:5:32 | AA | GenericTypeParamDecl | AA.Type [MetatypeType] |
|
||||
| Sources/deduplication/use.swift:5:36:5:36 | BB | GenericTypeParamDecl | BB.Type [MetatypeType] |
|
||||
| Sources/deduplication/use.swift:5:40:5:40 | CC | GenericTypeParamDecl | CC.Type [MetatypeType] |
|
||||
| Sources/deduplication/use.swift:5:44:5:47 | _ | ParamDecl | AA [GenericTypeParamType] |
|
||||
| Sources/deduplication/use.swift:5:51:5:54 | _ | ParamDecl | BB [GenericTypeParamType] |
|
||||
| Sources/deduplication/use.swift:5:58:5:61 | _ | ParamDecl | CC [GenericTypeParamType] |
|
||||
| Sources/deduplication/use.swift:6:1:6:45 | use_async_function_type(_:) | NamedFunction | (Int) async -> () [FunctionType] |
|
||||
| Sources/deduplication/use.swift:6:30:6:33 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/use.swift:7:1:7:49 | use_throwing_function_type(_:) | NamedFunction | (Int) throws -> () [FunctionType] |
|
||||
| Sources/deduplication/use.swift:7:33:7:36 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/use.swift:8:1:8:61 | use_async_throwing_function_type(_:) | NamedFunction | (Int) async throws -> () [FunctionType] |
|
||||
| Sources/deduplication/use.swift:8:39:8:42 | _ | ParamDecl | Int [StructType] |
|
||||
| Sources/deduplication/use.swift:9:1:9:150 | use_generic_function_with_conformance_type(_:_:_:) | NamedFunction | <AA, BB, CC where AA : Protocol1, AA : Protocol2, BB : Class, CC == AA.Associated> (AA, BB, CC) -> () [GenericFunctionType] |
|
||||
| Sources/deduplication/use.swift:9:49:9:49 | AA | GenericTypeParamDecl | AA.Type [MetatypeType] |
|
||||
| Sources/deduplication/use.swift:9:53:9:53 | BB | GenericTypeParamDecl | BB.Type [MetatypeType] |
|
||||
| Sources/deduplication/use.swift:9:57:9:57 | CC | GenericTypeParamDecl | CC.Type [MetatypeType] |
|
||||
| Sources/deduplication/use.swift:9:61:9:64 | _ | ParamDecl | AA [GenericTypeParamType] |
|
||||
| Sources/deduplication/use.swift:9:68:9:71 | _ | ParamDecl | BB [GenericTypeParamType] |
|
||||
| Sources/deduplication/use.swift:9:75:9:78 | _ | ParamDecl | CC [GenericTypeParamType] |
|
||||
| Sources/deduplication/use.swift:11:1:11:18 | extension of Class | ExtensionDecl | - |
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
import swift
|
||||
import Relevant
|
||||
|
||||
from Decl d
|
||||
where relevant(d)
|
||||
select d, d.getPrimaryQlClasses()
|
||||
from Decl d, string type
|
||||
where
|
||||
relevant(d) and
|
||||
(
|
||||
not exists(d.(ValueDecl).getInterfaceType()) and type = "-"
|
||||
or
|
||||
exists(Type t |
|
||||
t = d.(ValueDecl).getInterfaceType() and
|
||||
type = t.toString() + " [" + t.getPrimaryQlClasses() + "]"
|
||||
)
|
||||
)
|
||||
select d, d.getPrimaryQlClasses(), type
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
// swift-tools-version: 5.5
|
||||
// swift-tools-version: 5.7
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "deduplication",
|
||||
platforms: [
|
||||
.macOS(.v10_15),
|
||||
],
|
||||
products: [
|
||||
.library(
|
||||
name: "deduplication",
|
||||
|
|
|
@ -1,7 +1,36 @@
|
|||
var x = 42
|
||||
var def_int = 42
|
||||
|
||||
struct Generic<T> {}
|
||||
struct Generic<T> {
|
||||
func def_generic_method<U, V>(t: T, u: U, v: V) -> T { return t; }
|
||||
}
|
||||
|
||||
var instantiated_generic = Generic<Int>()
|
||||
var def_instantiated_generic = Generic<Int>()
|
||||
|
||||
func function(_: Int) -> Int { return 42 }
|
||||
func def_function(_: Int) -> Int { return 42 }
|
||||
|
||||
func def_function_overloaded_on_return(_: Int, _: Double) -> Int { return 0 }
|
||||
func def_function_overloaded_on_return(_: Int, _: Double) -> Double { return 0.0 }
|
||||
|
||||
func def_function_overloaded_on_parameter_type(_: Int) {}
|
||||
func def_function_overloaded_on_parameter_type(_: Double) {}
|
||||
|
||||
func def_function_overloaded_on_parameter_label(one x: Int) {}
|
||||
func def_function_overloaded_on_parameter_label(two x: Int) {}
|
||||
|
||||
func def_throwing_function(_: Int) throws {}
|
||||
func def_rethrowing_function(_: () throws -> ()) rethrows {}
|
||||
func def_async_function(_: Int) async {}
|
||||
func def_async_throwing_function(_: Int) async throws {}
|
||||
func def_async_rethrowing_function(_: () throws -> ()) async rethrows {}
|
||||
|
||||
func def_generic_function<A, B, C>(_: A, _: B, _: C) {}
|
||||
|
||||
protocol Protocol1 {}
|
||||
protocol Protocol2 {
|
||||
associatedtype Associated;
|
||||
}
|
||||
class Class {}
|
||||
|
||||
func def_generic_function_with_conformance<A : Protocol1 & Protocol2, B : Class, C>(_: A, _: B, _: C) where C == A.Associated {}
|
||||
|
||||
extension Class {}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
let use_x = x
|
||||
let use_instantiated_generic = instantiated_generic
|
||||
let use_function = function
|
||||
let use_int = def_int
|
||||
let use_instantiated_generic = def_instantiated_generic
|
||||
let answer = use_instantiated_generic.def_generic_method(t: 42, u: "hello", v: 0.0)
|
||||
let use_function = def_function
|
||||
func use_generic_function_type<AA, BB, CC>(_: AA, _: BB, _: CC) {}
|
||||
func use_async_function_type(_: Int) async {}
|
||||
func use_throwing_function_type(_: Int) throws {}
|
||||
func use_async_throwing_function_type(_: Int) async throws {}
|
||||
func use_generic_function_with_conformance_type<AA, BB, CC>(_: AA, _: BB, _: CC) where AA: Protocol1, AA: Protocol2, BB: Class, CC == AA.Associated {}
|
||||
|
||||
extension Class {}
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
| (Int) -> Int | FunctionType | function(_:) |
|
||||
| (Int) -> Int | FunctionType | use_function |
|
||||
| <T> (Generic<T>.Type) -> () -> Generic<T> | GenericFunctionType | Generic<T>.init() |
|
||||
| Generic<Int> | BoundGenericStructType | instantiated_generic |
|
||||
| Generic<Int> | BoundGenericStructType | use_instantiated_generic |
|
||||
| Generic<T> | BoundGenericStructType | self |
|
||||
| Generic<T>.Type | MetatypeType | Generic |
|
||||
| Int | StructType | _, x |
|
||||
| Int | StructType | use_x |
|
||||
| T.Type | MetatypeType | T |
|
||||
| (() throws -> ()) async throws -> () | FunctionType | def_async_rethrowing_function(_:) | |
|
||||
| (() throws -> ()) throws -> () | FunctionType | def_rethrowing_function(_:) | |
|
||||
| (Double) -> () | FunctionType | def_function_overloaded_on_parameter_type(_:) | |
|
||||
| (Int) -> () | FunctionType | def_function_overloaded_on_parameter_label(one:), def_function_overloaded_on_parameter_label(two:), def_function_overloaded_on_parameter_type(_:) | |
|
||||
| (Int) -> Int | FunctionType | def_function(_:), use_function | |
|
||||
| (Int) async -> () | FunctionType | def_async_function(_:), use_async_function_type(_:) | |
|
||||
| (Int) async throws -> () | FunctionType | def_async_throwing_function(_:), use_async_throwing_function_type(_:) | |
|
||||
| (Int) throws -> () | FunctionType | def_throwing_function(_:), use_throwing_function_type(_:) | |
|
||||
| (Int, Double) -> Double | FunctionType | def_function_overloaded_on_return(_:_:) | |
|
||||
| (Int, Double) -> Int | FunctionType | def_function_overloaded_on_return(_:_:) | |
|
||||
| <A, B, C where A : Protocol1, A : Protocol2, B : Class, C == A.Associated> (A, B, C) -> () | GenericFunctionType | def_generic_function_with_conformance(_:_:_:) | <\u03c4_0_0, \u03c4_0_1, \u03c4_0_2 where \u03c4_0_0 : Protocol1, \u03c4_0_0 : Protocol2, \u03c4_0_1 : Class, \u03c4_0_2 == \u03c4_0_0.Associated> (\u03c4_0_0, \u03c4_0_1, \u03c4_0_2) -> () |
|
||||
| <A, B, C> (A, B, C) -> () | GenericFunctionType | def_generic_function(_:_:_:) | <\u03c4_0_0, \u03c4_0_1, \u03c4_0_2> (\u03c4_0_0, \u03c4_0_1, \u03c4_0_2) -> () |
|
||||
| <AA, BB, CC where AA : Protocol1, AA : Protocol2, BB : Class, CC == AA.Associated> (AA, BB, CC) -> () | GenericFunctionType | use_generic_function_with_conformance_type(_:_:_:) | <\u03c4_0_0, \u03c4_0_1, \u03c4_0_2 where \u03c4_0_0 : Protocol1, \u03c4_0_0 : Protocol2, \u03c4_0_1 : Class, \u03c4_0_2 == \u03c4_0_0.Associated> (\u03c4_0_0, \u03c4_0_1, \u03c4_0_2) -> () |
|
||||
| <AA, BB, CC> (AA, BB, CC) -> () | GenericFunctionType | use_generic_function_type(_:_:_:) | <\u03c4_0_0, \u03c4_0_1, \u03c4_0_2> (\u03c4_0_0, \u03c4_0_1, \u03c4_0_2) -> () |
|
||||
| <T, U, V> (Generic<T>) -> (T, U, V) -> T | GenericFunctionType | def_generic_method(t:u:v:) | <\u03c4_0_0, \u03c4_1_0, \u03c4_1_1> (Generic<\u03c4_0_0>) -> (\u03c4_0_0, \u03c4_1_0, \u03c4_1_1) -> \u03c4_0_0 |
|
||||
| <\u03c4_0_0, \u03c4_0_1, \u03c4_0_2 where \u03c4_0_0 : Protocol1, \u03c4_0_0 : Protocol2, \u03c4_0_1 : Class, \u03c4_0_2 == \u03c4_0_0.Associated> (\u03c4_0_0, \u03c4_0_1, \u03c4_0_2) -> () | GenericFunctionType | def_generic_function_with_conformance(_:_:_:), use_generic_function_with_conformance_type(_:_:_:) | |
|
||||
| <\u03c4_0_0, \u03c4_0_1, \u03c4_0_2> (\u03c4_0_0, \u03c4_0_1, \u03c4_0_2) -> () | GenericFunctionType | def_generic_function(_:_:_:), use_generic_function_type(_:_:_:) | |
|
||||
| <\u03c4_0_0, \u03c4_1_0, \u03c4_1_1> (Generic<\u03c4_0_0>) -> (\u03c4_0_0, \u03c4_1_0, \u03c4_1_1) -> \u03c4_0_0 | GenericFunctionType | def_generic_method(t:u:v:) | |
|
||||
| Generic<Int> | BoundGenericStructType | def_instantiated_generic, use_instantiated_generic | |
|
||||
| Int | StructType | def_int, use_int | |
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
import swift
|
||||
import Relevant
|
||||
|
||||
from Type t, string decls
|
||||
from Type t, string decls, string canonical
|
||||
where
|
||||
decls = strictconcat(ValueDecl d | relevant(d) and t = d.getInterfaceType() | d.toString(), ", ")
|
||||
select t, t.getPrimaryQlClasses(), decls
|
||||
decls =
|
||||
strictconcat(ValueDecl d |
|
||||
relevant(d) and
|
||||
t = [d.getInterfaceType(), d.getInterfaceType().getCanonicalType()] and
|
||||
d.toString().matches(["use_%", "def_%"])
|
||||
|
|
||||
d.toString(), ", "
|
||||
) and
|
||||
if t = t.getCanonicalType() then canonical = "" else canonical = t.getCanonicalType().toString()
|
||||
select t, t.getPrimaryQlClasses(), decls, canonical
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
doubleIndexes
|
||||
| method_lookups.swift:44:11:44:13 | [AutoClosureExpr] { ... } | 2 | getParam(0) | 4 | getParam(1) | file://:0:0:0:0 | [ParamDecl] argument |
|
||||
| method_lookups.swift:44:11:44:13 | [AutoClosureExpr] { ... } | 4 | getParam(1) | 2 | getParam(0) | file://:0:0:0:0 | [ParamDecl] argument |
|
|
@ -0,0 +1,12 @@
|
|||
//codeql-extractor-options: -parse-stdlib
|
||||
func foo(
|
||||
_: Builtin.IntLiteral,
|
||||
_: Builtin.FPIEEE32,
|
||||
_: Builtin.FPIEEE64,
|
||||
_: Builtin.BridgeObject,
|
||||
_: Builtin.NativeObject,
|
||||
_: Builtin.RawPointer,
|
||||
_: Builtin.Executor,
|
||||
_: Builtin.Job,
|
||||
_: Builtin.RawUnsafeContinuation
|
||||
) {}
|
|
@ -1,3 +1,7 @@
|
|||
| Base | getName: | Base | getCanonicalType: | Base | getInterfaceType: | Base | hasSuperclass: | no | getNumberOfProtocols: | 1 |
|
||||
| Base | getName: | Base | getCanonicalType: | Base | getInterfaceType: | Base | hasSuperclass: | no | getNumberOfProtocols: | 1 |
|
||||
| Base | getName: | Base | getCanonicalType: | Base | getInterfaceType: | Base | hasSuperclass: | yes | getNumberOfProtocols: | 0 |
|
||||
| Base | getName: | Base | getCanonicalType: | Base | getInterfaceType: | Base | hasSuperclass: | yes | getNumberOfProtocols: | 0 |
|
||||
| Param | getName: | Param | getCanonicalType: | Param | getInterfaceType: | Param | hasSuperclass: | no | getNumberOfProtocols: | 0 |
|
||||
| ParamWithProtocols | getName: | ParamWithProtocols | getCanonicalType: | ParamWithProtocols | getInterfaceType: | ParamWithProtocols | hasSuperclass: | no | getNumberOfProtocols: | 2 |
|
||||
| ParamWithSuperclass | getName: | ParamWithSuperclass | getCanonicalType: | ParamWithSuperclass | getInterfaceType: | ParamWithSuperclass | hasSuperclass: | yes | getNumberOfProtocols: | 0 |
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
| Base | 0 | primary_archetypes.swift:4:1:4:13 | P |
|
||||
| Base | 0 | primary_archetypes.swift:5:1:5:14 | P2 |
|
||||
| ParamWithProtocols | 0 | file://:0:0:0:0 | Equatable |
|
||||
| ParamWithProtocols | 1 | primary_archetypes.swift:3:1:3:13 | P |
|
||||
| ParamWithProtocols | 1 | primary_archetypes.swift:4:1:4:13 | P |
|
||||
| ParamWithSuperclassAndProtocols | 0 | file://:0:0:0:0 | Equatable |
|
||||
| ParamWithSuperclassAndProtocols | 1 | primary_archetypes.swift:3:1:3:13 | P |
|
||||
| ParamWithSuperclassAndProtocols | 1 | primary_archetypes.swift:4:1:4:13 | P |
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
| Base | S |
|
||||
| Base | S2 |
|
||||
| ParamWithSuperclass | S |
|
||||
| ParamWithSuperclassAndProtocols | S |
|
||||
|
|
|
@ -1,9 +1,25 @@
|
|||
class S {}
|
||||
class S2 {}
|
||||
|
||||
protocol P {}
|
||||
protocol P2 {}
|
||||
|
||||
func foo<Param,
|
||||
ParamWithSuperclass: S,
|
||||
ParamWithProtocols: P & Equatable,
|
||||
ParamWithSuperclassAndProtocols: S & Equatable & P>(
|
||||
_: Param, _: ParamWithSuperclass, _: ParamWithProtocols, _: ParamWithSuperclassAndProtocols) {}
|
||||
|
||||
class Generic<Base> {}
|
||||
extension Generic where Base : P {
|
||||
func f(_: Base) {}
|
||||
}
|
||||
extension Generic where Base : P2 {
|
||||
func f(_: Base) {}
|
||||
}
|
||||
extension Generic where Base : S {
|
||||
func f(_: Base) {}
|
||||
}
|
||||
extension Generic where Base : S2 {
|
||||
func f(_: Base) {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
//codeql-extractor-options: -parse-stdlib
|
||||
func f(x : (Builtin.IntLiteral, Builtin.IntLiteral)) {}
|
Загрузка…
Ссылка в новой задаче