Skip to content

Commit 6a12dc0

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 77cb4b6 commit 6a12dc0

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"
@@ -853,6 +854,13 @@ class ASTContext final {
853854
ModuleDependenciesCache &cache,
854855
InterfaceSubContextDelegate &delegate);
855856

857+
/// Compute the extra implicit framework search paths on Apple platforms:
858+
/// $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/.
859+
std::vector<std::string> getDarwinImplicitFrameworkSearchPaths() const;
860+
861+
/// Return a set of all possible filesystem locations where modules can be found.
862+
llvm::StringSet<> getAllModuleSearchPathsSet() const;
863+
856864
/// Load extensions to the given nominal type from the external
857865
/// module loaders.
858866
///

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"
@@ -1641,29 +1642,32 @@ Optional<ModuleDependencies> ASTContext::getModuleDependencies(
16411642
bool cacheOnly) {
16421643
// Retrieve the dependencies for this module.
16431644
if (cacheOnly) {
1645+
auto searchPathSet = getAllModuleSearchPathsSet();
16441646
// Check whether we've cached this result.
16451647
if (!isUnderlyingClangModule) {
1646-
if (auto found = cache.findDependencies(moduleName,
1647-
ModuleDependenciesKind::SwiftTextual))
1648+
if (auto found = cache.findDependencies(
1649+
moduleName,
1650+
{ModuleDependenciesKind::SwiftTextual, searchPathSet}))
16481651
return found;
1649-
if (auto found = cache.findDependencies(moduleName,
1650-
ModuleDependenciesKind::SwiftTextual))
1652+
if (auto found = cache.findDependencies(
1653+
moduleName, {ModuleDependenciesKind::SwiftBinary, searchPathSet}))
16511654
return found;
1652-
if (auto found = cache.findDependencies(moduleName,
1653-
ModuleDependenciesKind::SwiftPlaceholder))
1655+
if (auto found = cache.findDependencies(
1656+
moduleName,
1657+
{ModuleDependenciesKind::SwiftPlaceholder, searchPathSet}))
16541658
return found;
16551659
}
1656-
if (auto found = cache.findDependencies(moduleName,
1657-
ModuleDependenciesKind::Clang))
1660+
if (auto found = cache.findDependencies(
1661+
moduleName, {ModuleDependenciesKind::Clang, searchPathSet}))
16581662
return found;
16591663
} else {
16601664
for (auto &loader : getImpl().ModuleLoaders) {
16611665
if (isUnderlyingClangModule &&
16621666
loader.get() != getImpl().TheClangModuleLoader)
16631667
continue;
16641668

1665-
if (auto dependencies = loader->getModuleDependencies(moduleName, cache,
1666-
delegate))
1669+
if (auto dependencies =
1670+
loader->getModuleDependencies(moduleName, cache, delegate))
16671671
return dependencies;
16681672
}
16691673
}
@@ -1686,6 +1690,65 @@ ASTContext::getSwiftModuleDependencies(StringRef moduleName,
16861690
return None;
16871691
}
16881692

1693+
namespace {
1694+
static StringRef
1695+
pathStringFromFrameworkSearchPath(const SearchPathOptions::FrameworkSearchPath &next) {
1696+
return next.Path;
1697+
};
1698+
}
1699+
1700+
std::vector<std::string> ASTContext::getDarwinImplicitFrameworkSearchPaths()
1701+
const {
1702+
assert(LangOpts.Target.isOSDarwin());
1703+
SmallString<128> systemFrameworksScratch;
1704+
systemFrameworksScratch = SearchPathOpts.SDKPath;
1705+
llvm::sys::path::append(systemFrameworksScratch, "System", "Library", "Frameworks");
1706+
1707+
SmallString<128> frameworksScratch;
1708+
frameworksScratch = SearchPathOpts.SDKPath;
1709+
llvm::sys::path::append(frameworksScratch, "Library", "Frameworks");
1710+
return {systemFrameworksScratch.str().str(), frameworksScratch.str().str()};
1711+
}
1712+
1713+
llvm::StringSet<> ASTContext::getAllModuleSearchPathsSet()
1714+
const {
1715+
llvm::StringSet<> result;
1716+
result.insert(SearchPathOpts.ImportSearchPaths.begin(),
1717+
SearchPathOpts.ImportSearchPaths.end());
1718+
1719+
// Framework paths are "special", they contain more than path strings,
1720+
// but path strings are all we care about here.
1721+
using FrameworkPathView = ArrayRefView<SearchPathOptions::FrameworkSearchPath,
1722+
StringRef,
1723+
pathStringFromFrameworkSearchPath>;
1724+
FrameworkPathView frameworkPathsOnly{SearchPathOpts.FrameworkSearchPaths};
1725+
result.insert(frameworkPathsOnly.begin(), frameworkPathsOnly.end());
1726+
1727+
if (LangOpts.Target.isOSDarwin()) {
1728+
auto implicitFrameworkSearchPaths = getDarwinImplicitFrameworkSearchPaths();
1729+
result.insert(implicitFrameworkSearchPaths.begin(),
1730+
implicitFrameworkSearchPaths.end());
1731+
}
1732+
result.insert(SearchPathOpts.RuntimeLibraryImportPaths.begin(),
1733+
SearchPathOpts.RuntimeLibraryImportPaths.end());
1734+
1735+
// ClangImporter special-cases the path for SwiftShims, so do the same here
1736+
// If there are no shims in the resource dir, add a search path in the SDK.
1737+
SmallString<128> shimsPath(SearchPathOpts.RuntimeResourcePath);
1738+
llvm::sys::path::append(shimsPath, "shims");
1739+
if (!llvm::sys::fs::exists(shimsPath)) {
1740+
shimsPath = SearchPathOpts.SDKPath;
1741+
llvm::sys::path::append(shimsPath, "usr", "lib", "swift", "shims");
1742+
}
1743+
result.insert(shimsPath.str());
1744+
1745+
// Clang system modules are found in the SDK root
1746+
SmallString<128> clangSysRootPath(SearchPathOpts.SDKPath);
1747+
llvm::sys::path::append(clangSysRootPath, "usr", "include");
1748+
result.insert(clangSysRootPath.str());
1749+
return result;
1750+
}
1751+
16891752
void ASTContext::loadExtensions(NominalTypeDecl *nominal,
16901753
unsigned previousGeneration) {
16911754
PrettyStackTraceDecl stackTrace("loading extensions for", nominal);

0 commit comments

Comments
 (0)