Skip to content

Commit 9bc036c

Browse files
committed
DependencyScanner: honor additional compiler flags in interfaces files when collecting imports
Additional flags in interface files may change parsing behavior like #if statements. We should use a fresh ASTContext with these additional flags when parsing interface files to collect imports. rdar://62612027
1 parent d9b1d8f commit 9bc036c

File tree

16 files changed

+185
-56
lines changed

16 files changed

+185
-56
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ namespace swift {
121121
class UnifiedStatsReporter;
122122
class IndexSubset;
123123
struct SILAutoDiffDerivativeFunctionKey;
124+
struct SubASTContextDelegate;
124125

125126
enum class KnownProtocolKind : uint8_t;
126127

@@ -719,7 +720,8 @@ class ASTContext final {
719720
Optional<ModuleDependencies> getModuleDependencies(
720721
StringRef moduleName,
721722
bool isUnderlyingClangModule,
722-
ModuleDependenciesCache &cache);
723+
ModuleDependenciesCache &cache,
724+
SubASTContextDelegate &delegate);
723725

724726
/// Load extensions to the given nominal type from the external
725727
/// module loaders.

include/swift/AST/ModuleLoader.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/SmallSet.h"
2626
#include "llvm/ADT/StringSet.h"
2727
#include "llvm/ADT/TinyPtrVector.h"
28+
#include "swift/AST/ModuleDependencies.h"
2829

2930
namespace llvm {
3031
class FileCollector;
@@ -84,6 +85,15 @@ class DependencyTracker {
8485
std::shared_ptr<clang::DependencyCollector> getClangCollector();
8586
};
8687

88+
/// Abstract interface to run an action in a sub ASTContext.
89+
struct SubASTContextDelegate {
90+
virtual bool runInSubContext(ASTContext &ctx, StringRef interfacePath,
91+
llvm::function_ref<bool(ASTContext&)> action) {
92+
llvm_unreachable("function should be overriden");
93+
}
94+
virtual ~SubASTContextDelegate() = default;
95+
};
96+
8797
/// Abstract interface that loads named modules into the AST.
8898
class ModuleLoader {
8999
virtual void anchor();
@@ -186,7 +196,7 @@ class ModuleLoader {
186196
/// if no such module exists.
187197
virtual Optional<ModuleDependencies> getModuleDependencies(
188198
StringRef moduleName,
189-
ModuleDependenciesCache &cache) = 0;
199+
ModuleDependenciesCache &cache, SubASTContextDelegate &delegate) = 0;
190200
};
191201

192202
} // namespace swift

include/swift/ClangImporter/ClangImporter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ class ClangImporter final : public ClangModuleLoader {
370370
void verifyAllModules() override;
371371

372372
Optional<ModuleDependencies> getModuleDependencies(
373-
StringRef moduleName, ModuleDependenciesCache &cache) override;
373+
StringRef moduleName, ModuleDependenciesCache &cache,
374+
SubASTContextDelegate &delegate) override;
374375

375376
/// Add dependency information for the bridging header.
376377
///

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
#include "swift/Basic/LLVM.h"
111111
#include "swift/Frontend/ModuleInterfaceSupport.h"
112112
#include "swift/Serialization/SerializedModuleLoader.h"
113+
#include "llvm/Support/StringSaver.h"
113114

114115
namespace clang {
115116
class CompilerInstance;
@@ -201,6 +202,14 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
201202
std::string
202203
getModuleCachePathFromClang(const clang::CompilerInstance &Instance);
203204

205+
bool extractSwiftInterfaceVersionAndArgs(SourceManager &SM,
206+
DiagnosticEngine &Diags,
207+
StringRef InterfacePath,
208+
version::Version &Vers,
209+
StringRef &CompilerVersion,
210+
llvm::StringSaver &SubArgSaver,
211+
SmallVectorImpl<const char *> &SubArgs,
212+
SourceLoc diagnosticLoc = SourceLoc());
204213
}
205214

206215
#endif

include/swift/Sema/SourceLoader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ class SourceLoader : public ModuleLoader {
9393
}
9494

9595
Optional<ModuleDependencies> getModuleDependencies(
96-
StringRef moduleName, ModuleDependenciesCache &cache) override {
96+
StringRef moduleName, ModuleDependenciesCache &cache,
97+
SubASTContextDelegate &delegate) override {
9798
// FIXME: Implement?
9899
return None;
99100
}

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
194194
virtual void verifyAllModules() override;
195195

196196
virtual Optional<ModuleDependencies> getModuleDependencies(
197-
StringRef moduleName, ModuleDependenciesCache &cache) override;
197+
StringRef moduleName, ModuleDependenciesCache &cache,
198+
SubASTContextDelegate &delegate) override;
198199
};
199200

200201
/// Imports serialized Swift modules into an ASTContext.

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,13 +1462,14 @@ void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader,
14621462

14631463
Optional<ModuleDependencies> ASTContext::getModuleDependencies(
14641464
StringRef moduleName, bool isUnderlyingClangModule,
1465-
ModuleDependenciesCache &cache) {
1465+
ModuleDependenciesCache &cache, SubASTContextDelegate &delegate) {
14661466
for (auto &loader : getImpl().ModuleLoaders) {
14671467
if (isUnderlyingClangModule &&
14681468
loader.get() != getImpl().TheClangModuleLoader)
14691469
continue;
14701470

1471-
if (auto dependencies = loader->getModuleDependencies(moduleName, cache))
1471+
if (auto dependencies = loader->getModuleDependencies(moduleName, cache,
1472+
delegate))
14721473
return dependencies;
14731474
}
14741475

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ static void recordModuleDependencies(
224224
}
225225

226226
Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
227-
StringRef moduleName, ModuleDependenciesCache &cache) {
227+
StringRef moduleName, ModuleDependenciesCache &cache,
228+
SubASTContextDelegate &delegate) {
228229
// Check whether there is already a cached result.
229230
if (auto found = cache.findDependencies(
230231
moduleName, ModuleDependenciesKind::Clang))

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#define DEBUG_TYPE "textual-module-interface"
1414

15+
#include "swift/Frontend/ModuleInterfaceLoader.h"
1516
#include "ModuleInterfaceBuilder.h"
1617
#include "swift/AST/ASTContext.h"
1718
#include "swift/AST/DiagnosticsFrontend.h"
@@ -134,35 +135,44 @@ void ModuleInterfaceBuilder::configureSubInvocation(
134135
remarkOnRebuildFromInterface;
135136
}
136137

137-
bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
138-
swift::version::Version &Vers, StringRef &CompilerVersion,
139-
llvm::StringSaver &SubArgSaver, SmallVectorImpl<const char *> &SubArgs) {
140-
llvm::vfs::FileSystem &fs = *sourceMgr.getFileSystem();
141-
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
138+
bool swift::extractSwiftInterfaceVersionAndArgs(
139+
SourceManager &SM,
140+
DiagnosticEngine &Diags,
141+
StringRef InterfacePath,
142+
version::Version &Vers,
143+
StringRef &CompilerVersion,
144+
llvm::StringSaver &SubArgSaver,
145+
SmallVectorImpl<const char *> &SubArgs,
146+
SourceLoc diagnosticLoc) {
147+
llvm::vfs::FileSystem &fs = *SM.getFileSystem();
148+
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, InterfacePath);
142149
if (!FileOrError) {
143150
// Don't use this->diagnose() because it'll just try to re-open
144151
// interfacePath.
145-
diags.diagnose(diagnosticLoc, diag::error_open_input_file,
146-
interfacePath, FileOrError.getError().message());
152+
Diags.diagnose(diagnosticLoc, diag::error_open_input_file,
153+
InterfacePath, FileOrError.getError().message());
147154
return true;
148155
}
149156
auto SB = FileOrError.get()->getBuffer();
150157
auto VersRe = getSwiftInterfaceFormatVersionRegex();
151158
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
152159
auto FlagRe = getSwiftInterfaceModuleFlagsRegex();
153160
SmallVector<StringRef, 1> VersMatches, FlagMatches, CompMatches;
161+
154162
if (!VersRe.match(SB, &VersMatches)) {
155-
diagnose(diag::error_extracting_version_from_module_interface);
163+
ModuleInterfaceBuilder::diagnose(Diags, SM, InterfacePath, diagnosticLoc,
164+
diag::error_extracting_version_from_module_interface);
156165
return true;
157166
}
158167
if (!FlagRe.match(SB, &FlagMatches)) {
159-
diagnose(diag::error_extracting_flags_from_module_interface);
168+
ModuleInterfaceBuilder::diagnose(Diags, SM, InterfacePath, diagnosticLoc,
169+
diag::error_extracting_version_from_module_interface);
160170
return true;
161171
}
162172
assert(VersMatches.size() == 2);
163173
assert(FlagMatches.size() == 2);
164174
// FIXME We should diagnose this at a location that makes sense:
165-
Vers = swift::version::Version(VersMatches[1], SourceLoc(), &diags);
175+
Vers = swift::version::Version(VersMatches[1], SourceLoc(), &Diags);
166176
llvm::cl::TokenizeGNUCommandLine(FlagMatches[1], SubArgSaver, SubArgs);
167177

168178
if (CompRe.match(SB, &CompMatches)) {
@@ -177,6 +187,13 @@ bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
177187
return false;
178188
}
179189

190+
bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
191+
swift::version::Version &Vers, StringRef &CompilerVersion,
192+
llvm::StringSaver &SubArgSaver, SmallVectorImpl<const char *> &SubArgs) {
193+
return swift::extractSwiftInterfaceVersionAndArgs(sourceMgr, diags,
194+
interfacePath, Vers, CompilerVersion, SubArgSaver, SubArgs, diagnosticLoc);
195+
}
196+
180197
bool ModuleInterfaceBuilder::collectDepsForSerialization(
181198
CompilerInstance &SubInstance, SmallVectorImpl<FileDependency> &Deps,
182199
bool IsHashBased) {

lib/Frontend/ModuleInterfaceBuilder.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,31 @@ class ModuleInterfaceBuilder {
4848
CompilerInvocation subInvocation;
4949
SmallVector<StringRef, 3> extraDependencies;
5050

51+
public:
5152
/// Emit a diagnostic tied to this declaration.
5253
template<typename ...ArgTypes>
53-
InFlightDiagnostic diagnose(
54+
static InFlightDiagnostic diagnose(
55+
DiagnosticEngine &Diags,
56+
SourceManager &SM,
57+
StringRef InterfacePath,
58+
SourceLoc Loc,
5459
Diag<ArgTypes...> ID,
55-
typename detail::PassArgument<ArgTypes>::type... Args) const {
56-
SourceLoc loc = diagnosticLoc;
57-
if (loc.isInvalid()) {
60+
typename detail::PassArgument<ArgTypes>::type... Args) {
61+
if (Loc.isInvalid()) {
5862
// Diagnose this inside the interface file, if possible.
59-
loc = sourceMgr.getLocFromExternalSource(interfacePath, 1, 1);
63+
Loc = SM.getLocFromExternalSource(InterfacePath, 1, 1);
6064
}
61-
return diags.diagnose(loc, ID, std::move(Args)...);
65+
return Diags.diagnose(Loc, ID, std::move(Args)...);
66+
}
67+
68+
private:
69+
/// Emit a diagnostic tied to this declaration.
70+
template<typename ...ArgTypes>
71+
InFlightDiagnostic diagnose(
72+
Diag<ArgTypes...> ID,
73+
typename detail::PassArgument<ArgTypes>::type... Args) const {
74+
return diagnose(diags, sourceMgr, interfacePath, diagnosticLoc,
75+
ID, std::move(Args)...);
6276
}
6377

6478
void configureSubInvocationInputsAndOutputs(StringRef OutPath);

lib/FrontendTool/ScanDependencies.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/Basic/STLExtras.h"
2525
#include "swift/Frontend/Frontend.h"
2626
#include "swift/Frontend/FrontendOptions.h"
27+
#include "swift/Frontend/ModuleInterfaceLoader.h"
2728
#include "swift/Strings.h"
2829
#include "clang/Basic/Module.h"
2930
#include "llvm/ADT/SetVector.h"
@@ -58,13 +59,48 @@ static void findAllImportedClangModules(ASTContext &ctx, StringRef moduleName,
5859
}
5960
}
6061

62+
struct InterfaceSubASTContextDelegate: SubASTContextDelegate {
63+
bool runInSubContext(ASTContext &ctx, StringRef interfacePath,
64+
llvm::function_ref<bool(ASTContext&)> action) override {
65+
// Parse the interface file using the current context to get the additional
66+
// compiler arguments we should use when creating a sub-ASTContext.
67+
// These arguments are in "swift-module-flags:"
68+
version::Version Vers;
69+
StringRef CompilerVersion;
70+
llvm::BumpPtrAllocator Allocator;
71+
llvm::StringSaver SubArgSaver(Allocator);
72+
SmallVector<const char *, 64> SubArgs;
73+
if (extractSwiftInterfaceVersionAndArgs(ctx.SourceMgr, ctx.Diags,
74+
interfacePath, Vers, CompilerVersion,
75+
SubArgSaver, SubArgs)) {
76+
return true;
77+
}
78+
CompilerInvocation invok;
79+
CompilerInstance inst;
80+
// Use the additional flags to setup the compiler instance.
81+
if (invok.parseArgs(SubArgs, ctx.Diags)) {
82+
return true;
83+
}
84+
if (inst.setup(invok)) {
85+
return true;
86+
}
87+
// Add the diag consumers to the sub context to make sure we don't lose
88+
// diagnostics.
89+
for (auto *consumer: ctx.Diags.getConsumers()) {
90+
inst.getDiags().addConsumer(*consumer);
91+
}
92+
// Run the action under the sub-ASTContext.
93+
return action(inst.getASTContext());
94+
}
95+
};
96+
6197
/// Resolve the direct dependencies of the given module.
6298
static std::vector<ModuleDependencyID> resolveDirectDependencies(
6399
ASTContext &ctx, ModuleDependencyID module,
64100
ModuleDependenciesCache &cache) {
65101
auto knownDependencies = *cache.findDependencies(module.first, module.second);
66102
auto isSwift = knownDependencies.isSwiftModule();
67-
103+
InterfaceSubASTContextDelegate ASTDelegate;
68104
// Find the dependencies of every module this module directly depends on.
69105
std::vector<ModuleDependencyID> result;
70106
for (auto dependsOn : knownDependencies.getModuleDependencies()) {
@@ -73,7 +109,7 @@ static std::vector<ModuleDependencyID> resolveDirectDependencies(
73109

74110
// Retrieve the dependencies for this module.
75111
if (auto found = ctx.getModuleDependencies(
76-
dependsOn, onlyClangModule, cache)) {
112+
dependsOn, onlyClangModule, cache, ASTDelegate)) {
77113
result.push_back({dependsOn, found->getKind()});
78114
}
79115
}
@@ -115,7 +151,7 @@ static std::vector<ModuleDependencyID> resolveDirectDependencies(
115151
// directly depends on these.
116152
for (const auto &clangDep : allClangModules) {
117153
if (auto found = ctx.getModuleDependencies(
118-
clangDep, /*onlyClangModule=*/false, cache)) {
154+
clangDep, /*onlyClangModule=*/false, cache, ASTDelegate)) {
119155
if (found->getKind() == ModuleDependenciesKind::Swift)
120156
result.push_back({clangDep, found->getKind()});
121157
}

0 commit comments

Comments
 (0)