Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Swift: Assign indexes to fileprivate ValueDecls
At least in the case of function declarations there can be multiple
identical ones within the same module, causing data set check errors
if not differentiated.
  • Loading branch information
jketema committed Apr 9, 2026
commit d09e2f66cd2686bddf0640b66a4cfa296fdcf77f
65 changes: 42 additions & 23 deletions swift/extractor/mangler/SwiftMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ std::string_view getTypeKindStr(const swift::TypeBase* type) {

} // namespace

std::unordered_map<const swift::Decl*, SwiftMangler::ExtensionIndex>
SwiftMangler::preloadedExtensionIndexes;
std::unordered_map<const swift::Decl*, SwiftMangler::ExtensionOrFilePrivateValueIndex>
SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes;

SwiftMangledName SwiftMangler::initMangled(const swift::TypeBase* type) {
return {getTypeKindStr(type), '_'};
Expand Down Expand Up @@ -75,6 +75,12 @@ SwiftMangledName SwiftMangler::visitValueDecl(const swift::ValueDecl* decl, bool
if (decl->isStatic()) {
ret << "|static";
}
if (decl->getFormalAccess() == swift::AccessLevel::FilePrivate) {
auto parent = getParent(decl);
auto index = getExtensionOrFilePrivateValueIndex(decl, parent);
ret << "|fileprivate" << index.index
<< (index.kind == ExtensionOrFilePrivateValueKind::clang ? "_clang" : "");
Comment thread
IdrissRio marked this conversation as resolved.
}
return ret;
}

Expand Down Expand Up @@ -105,51 +111,63 @@ SwiftMangledName SwiftMangler::visitExtensionDecl(const swift::ExtensionDecl* de

auto parent = getParent(decl);
auto target = decl->getExtendedType();
auto index = getExtensionIndex(decl, parent);
auto index = getExtensionOrFilePrivateValueIndex(decl, parent);
return initMangled(decl) << fetch(target) << index.index
<< (index.kind == ExtensionKind::clang ? "_clang" : "");
<< (index.kind == ExtensionOrFilePrivateValueKind::clang ? "_clang"
: "");
}

SwiftMangler::ExtensionIndex 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.
if (auto found = SwiftMangler::preloadedExtensionIndexes.find(decl);
found != SwiftMangler::preloadedExtensionIndexes.end()) {
SwiftMangler::ExtensionOrFilePrivateValueIndex SwiftMangler::getExtensionOrFilePrivateValueIndex(
const swift::Decl* decl,
const swift::Decl* parent) {
// to avoid iterating multiple times on the parent, we preload the indexes once for each
// encountered parent.
if (auto found = SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes.find(decl);
found != SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes.end()) {
return found->second;
}
if (auto parentModule = llvm::dyn_cast<swift::ModuleDecl>(parent)) {
llvm::SmallVector<swift::Decl*> siblings;
parentModule->getTopLevelDecls(siblings);
indexExtensions(siblings);
indexExtensionsAndFilePrivateValues(siblings);
if (auto clangModule = parentModule->findUnderlyingClangModule()) {
indexClangExtensions(clangModule, decl->getASTContext().getClangModuleLoader());
indexClangExtensionsAndFilePrivateValues(clangModule,
decl->getASTContext().getClangModuleLoader());
}
} else if (auto iterableParent = llvm::dyn_cast<swift::IterableDeclContext>(parent)) {
indexExtensions(iterableParent->getAllMembers());
indexExtensionsAndFilePrivateValues(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 = SwiftMangler::preloadedExtensionIndexes.find(decl);
auto found = SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes.find(decl);
// TODO use a generic logging handle for Swift entities here, once it's available
CODEQL_ASSERT(found != SwiftMangler::preloadedExtensionIndexes.end(),
"extension not found within parent");
CODEQL_ASSERT(found != SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes.end(),
"declaration not found within parent");
return found->second;
}

void SwiftMangler::indexExtensions(llvm::ArrayRef<swift::Decl*> siblings) {
bool SwiftMangler::isExtensionOrFilePrivateValue(const swift::Decl* decl) {
return decl->getKind() == swift::DeclKind::Extension ||
(swift::isa<swift::ValueDecl>(decl) &&
Comment thread
IdrissRio marked this conversation as resolved.
Outdated
swift::dyn_cast<swift::ValueDecl>(decl)->getFormalAccess() ==
swift::AccessLevel::FilePrivate);
}

void SwiftMangler::indexExtensionsAndFilePrivateValues(llvm::ArrayRef<swift::Decl*> siblings) {
auto index = 0u;
for (auto sibling : siblings) {
if (sibling->getKind() == swift::DeclKind::Extension) {
SwiftMangler::preloadedExtensionIndexes.try_emplace(sibling, ExtensionKind::swift, index);
if (isExtensionOrFilePrivateValue(sibling)) {
SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes.try_emplace(
sibling, ExtensionOrFilePrivateValueKind::swift, index);
index++;
}
}
}

void SwiftMangler::indexClangExtensions(const clang::Module* clangModule,
swift::ClangModuleLoader* moduleLoader) {
void SwiftMangler::indexClangExtensionsAndFilePrivateValues(
const clang::Module* clangModule,
swift::ClangModuleLoader* moduleLoader) {
if (!moduleLoader) {
return;
}
Expand All @@ -160,8 +178,9 @@ void SwiftMangler::indexClangExtensions(const clang::Module* clangModule,
llvm::SmallVector<swift::Decl*> children;
swiftSubmodule->getTopLevelDecls(children);
for (const auto child : children) {
if (child->getKind() == swift::DeclKind::Extension) {
SwiftMangler::preloadedExtensionIndexes.try_emplace(child, ExtensionKind::clang, index);
if (isExtensionOrFilePrivateValue(child)) {
SwiftMangler::preloadedExtensionOrFilePrivateValueIndexes.try_emplace(
child, ExtensionOrFilePrivateValueKind::clang, index);
index++;
}
}
Expand Down
19 changes: 11 additions & 8 deletions swift/extractor/mangler/SwiftMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,29 @@ class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
SwiftMangledName visitPackExpansionType(const swift::PackExpansionType* type);

private:
enum class ExtensionKind : bool {
enum class ExtensionOrFilePrivateValueKind : bool {
swift,
clang,
};

struct ExtensionIndex {
const ExtensionKind kind : 1;
struct ExtensionOrFilePrivateValueIndex {
const ExtensionOrFilePrivateValueKind kind : 1;
const uint32_t index : 31;
};

static std::unordered_map<const swift::Decl*, ExtensionIndex> preloadedExtensionIndexes;
static std::unordered_map<const swift::Decl*, ExtensionOrFilePrivateValueIndex>
preloadedExtensionOrFilePrivateValueIndexes;

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);
void indexClangExtensions(const clang::Module* clangModule,
swift::ClangModuleLoader* moduleLoader);
ExtensionIndex getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
bool isExtensionOrFilePrivateValue(const swift::Decl* decl);
void indexExtensionsAndFilePrivateValues(llvm::ArrayRef<swift::Decl*> siblings);
void indexClangExtensionsAndFilePrivateValues(const clang::Module* clangModule,
swift::ClangModuleLoader* moduleLoader);
ExtensionOrFilePrivateValueIndex getExtensionOrFilePrivateValueIndex(const swift::Decl* decl,
const swift::Decl* parent);
static SwiftMangledName initMangled(const swift::TypeBase* type);
SwiftMangledName initMangled(const swift::Decl* decl);
SwiftMangledName visitTypeDiscriminatedValueDecl(const swift::ValueDecl* decl);
Expand Down