Skip to content

Commit 3e8fea9

Browse files
committed
[Dependency Scanning] Have the scanner cache answer queries relevant to current search paths only.
The dependency scanner's cache persists across different queries and answering a subsequent query's module lookup with a module not in the query's search path is not correct. For example, suppose we are looking for a Swift module `Foo` with a set of search paths `SP`. And dependency scanner cache already contains a module `Foo`, for which we found an interface file at location `L`. If `L`∉`SP`, then we cannot re-use the cached entry because we’d be resolving the scanning query to a filesystem location that the current scanning context is not aware of. Resolves rdar://81175942
1 parent 5edb6e9 commit 3e8fea9

File tree

11 files changed

+479
-140
lines changed

11 files changed

+479
-140
lines changed

include/swift/AST/ASTContext.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "llvm/ADT/PointerIntPair.h"
3838
#include "llvm/ADT/SetVector.h"
3939
#include "llvm/ADT/SmallPtrSet.h"
40+
#include "llvm/ADT/StringSet.h"
4041
#include "llvm/ADT/StringMap.h"
4142
#include "llvm/ADT/TinyPtrVector.h"
4243
#include "llvm/Support/Allocator.h"
@@ -825,6 +826,13 @@ class ASTContext final {
825826
ModuleDependenciesCache &cache,
826827
InterfaceSubContextDelegate &delegate);
827828

829+
/// Compute the extra implicit framework search paths on Apple platforms:
830+
/// $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/.
831+
std::vector<std::string> getDarwinImplicitFrameworkSearchPaths() const;
832+
833+
/// Return a set of all possible filesystem locations where modules can be found.
834+
llvm::StringSet<> getAllModuleSearchPathsSet() const;
835+
828836
/// Load extensions to the given nominal type from the external
829837
/// module loaders.
830838
///

include/swift/AST/ModuleDependencies.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ enum class ModuleDependenciesKind : int8_t {
6363
Clang,
6464
};
6565

66+
/// Details of a given module used for dependency scanner cache queries.
67+
struct ModuleLookupSpecifics {
68+
Optional<ModuleDependenciesKind> kind;
69+
llvm::StringSet<> currentSearchPaths;
70+
};
71+
6672
/// Base class for the variant storage of ModuleDependencies.
6773
///
6874
/// This class is mostly an implementation detail for \c ModuleDependencies.
@@ -407,21 +413,25 @@ using ModuleDependencyID = std::pair<std::string, ModuleDependenciesKind>;
407413
/// A cache describing the set of module dependencies that has been queried
408414
/// thus far.
409415
class ModuleDependenciesCache {
416+
using ModuleDependenciesVector = llvm::SmallVector<ModuleDependencies, 1>;
417+
410418
/// All cached module dependencies, in the order in which they were
411419
/// encountered.
412420
std::vector<ModuleDependencyID> AllModules;
413421

414422
/// Dependencies for Textual Swift modules that have already been computed.
415-
llvm::StringMap<ModuleDependencies> SwiftTextualModuleDependencies;
423+
/// This maps a module's id (name, kind) to a vector of Dependency objects, which correspond
424+
/// to instances of the same module that may have been found in different sets of search paths.
425+
llvm::StringMap<ModuleDependenciesVector> SwiftTextualModuleDependencies;
416426

417427
/// Dependencies for Binary Swift modules that have already been computed.
418-
llvm::StringMap<ModuleDependencies> SwiftBinaryModuleDependencies;
428+
llvm::StringMap<ModuleDependenciesVector> SwiftBinaryModuleDependencies;
419429

420430
/// Dependencies for Swift placeholder dependency modules that have already been computed.
421-
llvm::StringMap<ModuleDependencies> SwiftPlaceholderModuleDependencies;
431+
llvm::StringMap<ModuleDependenciesVector> SwiftPlaceholderModuleDependencies;
422432

423433
/// Dependencies for Clang modules that have already been computed.
424-
llvm::StringMap<ModuleDependencies> ClangModuleDependencies;
434+
llvm::StringMap<ModuleDependenciesVector> ClangModuleDependencies;
425435

426436
/// Additional information needed for Clang dependency scanning.
427437
ClangModuleDependenciesCacheImpl *clangImpl = nullptr;
@@ -437,9 +447,9 @@ class ModuleDependenciesCache {
437447

438448
/// Retrieve the dependencies map that corresponds to the given dependency
439449
/// kind.
440-
llvm::StringMap<ModuleDependencies> &getDependenciesMap(
450+
llvm::StringMap<ModuleDependenciesVector> &getDependenciesMap(
441451
ModuleDependenciesKind kind);
442-
const llvm::StringMap<ModuleDependencies> &getDependenciesMap(
452+
const llvm::StringMap<ModuleDependenciesVector> &getDependenciesMap(
443453
ModuleDependenciesKind kind) const;
444454

445455
public:
@@ -469,12 +479,21 @@ class ModuleDependenciesCache {
469479

470480
/// Whether we have cached dependency information for the given module.
471481
bool hasDependencies(StringRef moduleName,
472-
Optional<ModuleDependenciesKind> kind) const;
482+
ModuleLookupSpecifics details) const;
473483

474-
/// Look for module dependencies for a module with the given name.
484+
/// Look for module dependencies for a module with the given name given current search paths.
475485
///
476486
/// \returns the cached result, or \c None if there is no cached entry.
477487
Optional<ModuleDependencies> findDependencies(
488+
StringRef moduleName,
489+
ModuleLookupSpecifics details) const;
490+
491+
/// Look for module dependencies for a module with the given name.
492+
/// This method has a deliberately-obtuse name to indicate that it is not to be used for general
493+
/// queries.
494+
///
495+
/// \returns the cached result, or \c None if there is no cached entry.
496+
Optional<ModuleDependenciesVector> findAllDependenciesIrrespectiveOfSearchPaths(
478497
StringRef moduleName,
479498
Optional<ModuleDependenciesKind> kind) const;
480499

lib/AST/ASTContext.cpp

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "swift/AST/PropertyWrappers.h"
4242
#include "swift/AST/ProtocolConformance.h"
4343
#include "swift/AST/RawComment.h"
44+
#include "swift/AST/SearchPathOptions.h"
4445
#include "swift/AST/SILLayout.h"
4546
#include "swift/AST/SemanticAttrs.h"
4647
#include "swift/AST/SourceFile.h"
@@ -1573,29 +1574,32 @@ Optional<ModuleDependencies> ASTContext::getModuleDependencies(
15731574
bool cacheOnly) {
15741575
// Retrieve the dependencies for this module.
15751576
if (cacheOnly) {
1577+
auto searchPathSet = getAllModuleSearchPathsSet();
15761578
// Check whether we've cached this result.
15771579
if (!isUnderlyingClangModule) {
1578-
if (auto found = cache.findDependencies(moduleName,
1579-
ModuleDependenciesKind::SwiftTextual))
1580+
if (auto found = cache.findDependencies(
1581+
moduleName,
1582+
{ModuleDependenciesKind::SwiftTextual, searchPathSet}))
15801583
return found;
1581-
if (auto found = cache.findDependencies(moduleName,
1582-
ModuleDependenciesKind::SwiftTextual))
1584+
if (auto found = cache.findDependencies(
1585+
moduleName, {ModuleDependenciesKind::SwiftBinary, searchPathSet}))
15831586
return found;
1584-
if (auto found = cache.findDependencies(moduleName,
1585-
ModuleDependenciesKind::SwiftPlaceholder))
1587+
if (auto found = cache.findDependencies(
1588+
moduleName,
1589+
{ModuleDependenciesKind::SwiftPlaceholder, searchPathSet}))
15861590
return found;
15871591
}
1588-
if (auto found = cache.findDependencies(moduleName,
1589-
ModuleDependenciesKind::Clang))
1592+
if (auto found = cache.findDependencies(
1593+
moduleName, {ModuleDependenciesKind::Clang, searchPathSet}))
15901594
return found;
15911595
} else {
15921596
for (auto &loader : getImpl().ModuleLoaders) {
15931597
if (isUnderlyingClangModule &&
15941598
loader.get() != getImpl().TheClangModuleLoader)
15951599
continue;
15961600

1597-
if (auto dependencies = loader->getModuleDependencies(moduleName, cache,
1598-
delegate))
1601+
if (auto dependencies =
1602+
loader->getModuleDependencies(moduleName, cache, delegate))
15991603
return dependencies;
16001604
}
16011605
}
@@ -1618,6 +1622,65 @@ ASTContext::getSwiftModuleDependencies(StringRef moduleName,
16181622
return None;
16191623
}
16201624

1625+
namespace {
1626+
static StringRef
1627+
pathStringFromFrameworkSearchPath(const SearchPathOptions::FrameworkSearchPath &next) {
1628+
return next.Path;
1629+
};
1630+
}
1631+
1632+
std::vector<std::string> ASTContext::getDarwinImplicitFrameworkSearchPaths()
1633+
const {
1634+
assert(LangOpts.Target.isOSDarwin());
1635+
SmallString<128> systemFrameworksScratch;
1636+
systemFrameworksScratch = SearchPathOpts.SDKPath;
1637+
llvm::sys::path::append(systemFrameworksScratch, "System", "Library", "Frameworks");
1638+
1639+
SmallString<128> frameworksScratch;
1640+
frameworksScratch = SearchPathOpts.SDKPath;
1641+
llvm::sys::path::append(frameworksScratch, "Library", "Frameworks");
1642+
return {systemFrameworksScratch.str().str(), frameworksScratch.str().str()};
1643+
}
1644+
1645+
llvm::StringSet<> ASTContext::getAllModuleSearchPathsSet()
1646+
const {
1647+
llvm::StringSet<> result;
1648+
result.insert(SearchPathOpts.ImportSearchPaths.begin(),
1649+
SearchPathOpts.ImportSearchPaths.end());
1650+
1651+
// Framework paths are "special", they contain more than path strings,
1652+
// but path strings are all we care about here.
1653+
using FrameworkPathView = ArrayRefView<SearchPathOptions::FrameworkSearchPath,
1654+
StringRef,
1655+
pathStringFromFrameworkSearchPath>;
1656+
FrameworkPathView frameworkPathsOnly{SearchPathOpts.FrameworkSearchPaths};
1657+
result.insert(frameworkPathsOnly.begin(), frameworkPathsOnly.end());
1658+
1659+
if (LangOpts.Target.isOSDarwin()) {
1660+
auto implicitFrameworkSearchPaths = getDarwinImplicitFrameworkSearchPaths();
1661+
result.insert(implicitFrameworkSearchPaths.begin(),
1662+
implicitFrameworkSearchPaths.end());
1663+
}
1664+
result.insert(SearchPathOpts.RuntimeLibraryImportPaths.begin(),
1665+
SearchPathOpts.RuntimeLibraryImportPaths.end());
1666+
1667+
// ClangImporter special-cases the path for SwiftShims, so do the same here
1668+
// If there are no shims in the resource dir, add a search path in the SDK.
1669+
SmallString<128> shimsPath(SearchPathOpts.RuntimeResourcePath);
1670+
llvm::sys::path::append(shimsPath, "shims");
1671+
if (!llvm::sys::fs::exists(shimsPath)) {
1672+
shimsPath = SearchPathOpts.SDKPath;
1673+
llvm::sys::path::append(shimsPath, "usr", "lib", "swift", "shims");
1674+
}
1675+
result.insert(shimsPath.str());
1676+
1677+
// Clang system modules are found in the SDK root
1678+
SmallString<128> clangSysRootPath(SearchPathOpts.SDKPath);
1679+
llvm::sys::path::append(clangSysRootPath, "usr", "include");
1680+
result.insert(clangSysRootPath.str());
1681+
return result;
1682+
}
1683+
16211684
void ASTContext::loadExtensions(NominalTypeDecl *nominal,
16221685
unsigned previousGeneration) {
16231686
PrettyStackTraceDecl stackTrace("loading extensions for", nominal);

0 commit comments

Comments
 (0)