Skip to content

Commit fc7e0ec

Browse files
authored
Merge pull request #9615 from github/redsun82/swift-fix-synthesized-entities
Swift: fix emission of synthesized entities
2 parents 2936e1a + 90f0e3e commit fc7e0ec

File tree

8 files changed

+61
-45
lines changed

8 files changed

+61
-45
lines changed

swift/extractor/SwiftDispatcher.h

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,25 @@
1010

1111
namespace codeql {
1212

13-
enum class SwiftExtractionMode { Module, PrimaryFile };
14-
1513
// The main responsibilities of the SwiftDispatcher are as follows:
1614
// * redirect specific AST node emission to a corresponding visitor (statements, expressions, etc.)
1715
// * storing TRAP labels for emitted AST nodes (in the TrapLabelStore) to avoid re-emission
1816
// Since SwiftDispatcher sees all the AST nodes, it also attaches a location to every 'locatable'
1917
// node (AST nodes that are not types: declarations, statements, expressions, etc.).
2018
class SwiftDispatcher {
2119
public:
22-
// all references passed as parameters to this constructor are supposed to outlive the
23-
// SwiftDispatcher
20+
// all references and pointers passed as parameters to this constructor are supposed to outlive
21+
// the SwiftDispatcher
2422
SwiftDispatcher(const swift::SourceManager& sourceManager,
2523
TrapArena& arena,
2624
TrapOutput& trap,
27-
SwiftExtractionMode extractionMode,
2825
swift::ModuleDecl& currentModule,
29-
llvm::StringRef currentFileName)
26+
swift::SourceFile* currentPrimarySourceFile = nullptr)
3027
: sourceManager{sourceManager},
3128
arena{arena},
3229
trap{trap},
33-
extractionMode(extractionMode),
3430
currentModule{currentModule},
35-
currentFileName(currentFileName) {}
31+
currentPrimarySourceFile{currentPrimarySourceFile} {}
3632

3733
template <typename Entry>
3834
void emit(const Entry& entry) {
@@ -135,29 +131,22 @@ class SwiftDispatcher {
135131

136132
// In order to not emit duplicated entries for declarations, we restrict emission to only
137133
// Decls declared within the current "scope".
138-
// Depending on the SwiftExtractionMode the scope is defined as follows:
139-
// - SwiftExtractionMode::Module: the current scope means the current module. This is used in
140-
// the case of system or builtin modules.
141-
// - SwiftExtractionMode::PrimaryFile: in this mode, we extract several files belonging to the
134+
// Depending on the whether we are extracting a primary source file or not the scope is defined as
135+
// follows:
136+
// - not extracting a primary source file (`currentPrimarySourceFile == nullptr`): the current
137+
// scope means the current module. This is used in the case of system or builtin modules.
138+
// - extracting a primary source file: in this mode, we extract several files belonging to the
142139
// same module one by one. In this mode, we restrict emission only to the same file ignoring
143140
// all the other files.
144-
// TODO this currently does not extract compiler-synthesized entities without a valid location,
145-
// this will be fixed in an upcoming PR
146141
bool shouldEmitDeclBody(swift::Decl* decl) {
147-
switch (extractionMode) {
148-
case SwiftExtractionMode::Module: {
149-
return &currentModule == decl->getModuleContext();
150-
} break;
151-
case SwiftExtractionMode::PrimaryFile: {
152-
swift::SourceLoc location = decl->getStartLoc();
153-
if (!location.isValid()) {
154-
return false;
155-
}
156-
auto declFileName = sourceManager.getDisplayNameForLoc(location).str();
157-
return &currentModule == decl->getModuleContext() && declFileName == currentFileName;
158-
} break;
159-
default:
160-
return false;
142+
if (decl->getModuleContext() != &currentModule) {
143+
return false;
144+
}
145+
if (!currentPrimarySourceFile) {
146+
return true;
147+
}
148+
if (auto context = decl->getDeclContext()) {
149+
return currentPrimarySourceFile == context->getParentSourceFile();
161150
}
162151
return false;
163152
}
@@ -241,9 +230,8 @@ class SwiftDispatcher {
241230
TrapOutput& trap;
242231
Store store;
243232
Store::Handle waitingForNewLabel{std::monostate{}};
244-
SwiftExtractionMode extractionMode;
245233
swift::ModuleDecl& currentModule;
246-
llvm::StringRef currentFileName;
234+
swift::SourceFile* currentPrimarySourceFile;
247235
};
248236

249237
} // namespace codeql

swift/extractor/SwiftExtractor.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,16 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
5050
}
5151

5252
static void extractDeclarations(const SwiftExtractorConfiguration& config,
53+
llvm::ArrayRef<swift::Decl*> topLevelDecls,
5354
swift::CompilerInstance& compiler,
54-
SwiftExtractionMode extractionMode,
5555
swift::ModuleDecl& module,
56-
llvm::StringRef fileName,
57-
llvm::ArrayRef<swift::Decl*> topLevelDecls) {
56+
swift::SourceFile* primaryFile = nullptr) {
5857
// The extractor can be called several times from different processes with
5958
// the same input file(s)
6059
// We are using PID to avoid concurrent access
6160
// TODO: find a more robust approach to avoid collisions?
62-
std::string tempTrapName = fileName.str() + '.' + std::to_string(getpid()) + ".trap";
61+
llvm::StringRef filename = primaryFile ? primaryFile->getFilename() : module.getModuleFilename();
62+
std::string tempTrapName = filename.str() + '.' + std::to_string(getpid()) + ".trap";
6363
llvm::SmallString<PATH_MAX> tempTrapPath(config.trapDir);
6464
llvm::sys::path::append(tempTrapPath, tempTrapName);
6565

@@ -96,22 +96,22 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
9696
trap.assignKey(unknownLocationLabel, "unknown");
9797
trap.emit(LocationsTrap{unknownLocationLabel, unknownFileLabel});
9898

99-
SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap, extractionMode, module, fileName);
99+
SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap, module, primaryFile);
100100
for (auto decl : topLevelDecls) {
101101
visitor.extract(decl);
102102
}
103103
if (topLevelDecls.empty()) {
104104
// In the case of empty files, the dispatcher is not called, but we still want to 'record' the
105105
// fact that the file was extracted
106-
llvm::SmallString<PATH_MAX> name(fileName);
106+
llvm::SmallString<PATH_MAX> name(filename);
107107
llvm::sys::fs::make_absolute(name);
108108
auto fileLabel = arena.allocateLabel<FileTag>();
109109
trap.assignKey(fileLabel, name.str().str());
110110
trap.emit(FilesTrap{fileLabel, name.str().str()});
111111
}
112112

113113
// TODO: Pick a better name to avoid collisions
114-
std::string trapName = fileName.str() + ".trap";
114+
std::string trapName = filename.str() + ".trap";
115115
llvm::SmallString<PATH_MAX> trapPath(config.trapDir);
116116
llvm::sys::path::append(trapPath, trapName);
117117

@@ -133,15 +133,14 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
133133
llvm::SmallVector<swift::Decl*> decls;
134134
module->getTopLevelDecls(decls);
135135
// TODO: pass ModuleDecl directly when we have module extraction in place?
136-
extractDeclarations(config, compiler, SwiftExtractionMode::Module, *module,
137-
module->getModuleFilename(), decls);
136+
extractDeclarations(config, decls, compiler, *module);
138137
} else {
139138
// The extraction will only work if one (or more) `-primary-file` CLI option is provided,
140139
// which is what always happens in case of `swift build` and `xcodebuild`
141140
for (auto primaryFile : module->getPrimarySourceFiles()) {
142141
archiveFile(config, *primaryFile);
143-
extractDeclarations(config, compiler, SwiftExtractionMode::PrimaryFile, *module,
144-
primaryFile->getFilename(), primaryFile->getTopLevelDecls());
142+
extractDeclarations(config, primaryFile->getTopLevelDecls(), compiler, *module,
143+
primaryFile);
145144
}
146145
}
147146
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// generated by codegen/codegen.py
2+
import codeql.swift.elements
3+
import TestUtils
4+
5+
from EnumDecl x, Type getInterfaceType, string getName, Type getType
6+
where
7+
toBeTested(x) and
8+
not x.isUnknown() and
9+
getInterfaceType = x.getInterfaceType() and
10+
getName = x.getName() and
11+
getType = x.getType()
12+
select x, "getInterfaceType:", getInterfaceType, "getName:", getName, "getType:", getType
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// generated by codegen/codegen.py
2+
import codeql.swift.elements
3+
import TestUtils
4+
5+
from EnumDecl x, int index
6+
where toBeTested(x) and not x.isUnknown()
7+
select x, index, x.getBaseType(index)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// generated by codegen/codegen.py
2+
import codeql.swift.elements
3+
import TestUtils
4+
5+
from EnumDecl x, int index
6+
where toBeTested(x) and not x.isUnknown()
7+
select x, index, x.getGenericTypeParam(index)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// generated by codegen/codegen.py
2+
import codeql.swift.elements
3+
import TestUtils
4+
5+
from EnumDecl x, int index
6+
where toBeTested(x) and not x.isUnknown()
7+
select x, index, x.getMember(index)

swift/ql/test/extractor-tests/generated/decl/EnumDecl/MISSING_SOURCE.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)