Skip to content

DependencyScanner: honor additional compiler flags in interfaces files when collecting imports #31553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 3 additions & 1 deletion include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ namespace swift {
class UnifiedStatsReporter;
class IndexSubset;
struct SILAutoDiffDerivativeFunctionKey;
struct SubASTContextDelegate;

enum class KnownProtocolKind : uint8_t;

Expand Down Expand Up @@ -719,7 +720,8 @@ class ASTContext final {
Optional<ModuleDependencies> getModuleDependencies(
StringRef moduleName,
bool isUnderlyingClangModule,
ModuleDependenciesCache &cache);
ModuleDependenciesCache &cache,
SubASTContextDelegate &delegate);

/// Load extensions to the given nominal type from the external
/// module loaders.
Expand Down
12 changes: 11 additions & 1 deletion include/swift/AST/ModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "swift/AST/ModuleDependencies.h"

namespace llvm {
class FileCollector;
Expand Down Expand Up @@ -84,6 +85,15 @@ class DependencyTracker {
std::shared_ptr<clang::DependencyCollector> getClangCollector();
};

/// Abstract interface to run an action in a sub ASTContext.
struct SubASTContextDelegate {
virtual bool runInSubContext(ASTContext &ctx, StringRef interfacePath,
llvm::function_ref<bool(ASTContext&)> action) {
llvm_unreachable("function should be overriden");
}
virtual ~SubASTContextDelegate() = default;
};

/// Abstract interface that loads named modules into the AST.
class ModuleLoader {
virtual void anchor();
Expand Down Expand Up @@ -186,7 +196,7 @@ class ModuleLoader {
/// if no such module exists.
virtual Optional<ModuleDependencies> getModuleDependencies(
StringRef moduleName,
ModuleDependenciesCache &cache) = 0;
ModuleDependenciesCache &cache, SubASTContextDelegate &delegate) = 0;
};

} // namespace swift
Expand Down
3 changes: 2 additions & 1 deletion include/swift/ClangImporter/ClangImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@ class ClangImporter final : public ClangModuleLoader {
void verifyAllModules() override;

Optional<ModuleDependencies> getModuleDependencies(
StringRef moduleName, ModuleDependenciesCache &cache) override;
StringRef moduleName, ModuleDependenciesCache &cache,
SubASTContextDelegate &delegate) override;

/// Add dependency information for the bridging header.
///
Expand Down
14 changes: 14 additions & 0 deletions include/swift/Frontend/ModuleInterfaceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
#include "swift/Basic/LLVM.h"
#include "swift/Frontend/ModuleInterfaceSupport.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "llvm/Support/StringSaver.h"

namespace clang {
class CompilerInstance;
Expand All @@ -123,6 +124,7 @@ namespace swift {

class LangOptions;
class SearchPathOptions;
class CompilerInvocation;

/// A ModuleLoader that runs a subordinate \c CompilerInvocation and
/// \c CompilerInstance to convert .swiftinterface files to .swiftmodule
Expand Down Expand Up @@ -201,6 +203,18 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
std::string
getModuleCachePathFromClang(const clang::CompilerInstance &Instance);

bool extractSwiftInterfaceVersionAndArgs(SourceManager &SM,
DiagnosticEngine &Diags,
StringRef InterfacePath,
version::Version &Vers,
StringRef &CompilerVersion,
llvm::StringSaver &SubArgSaver,
SmallVectorImpl<const char *> &SubArgs,
SourceLoc diagnosticLoc = SourceLoc());

void inheritOptionsForBuildingInterface(CompilerInvocation &Invok,
const SearchPathOptions &SearchPathOpts,
const LangOptions &LangOpts);
}

#endif
3 changes: 2 additions & 1 deletion include/swift/Sema/SourceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ class SourceLoader : public ModuleLoader {
}

Optional<ModuleDependencies> getModuleDependencies(
StringRef moduleName, ModuleDependenciesCache &cache) override {
StringRef moduleName, ModuleDependenciesCache &cache,
SubASTContextDelegate &delegate) override {
// FIXME: Implement?
return None;
}
Expand Down
3 changes: 2 additions & 1 deletion include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ class SerializedModuleLoaderBase : public ModuleLoader {
virtual void verifyAllModules() override;

virtual Optional<ModuleDependencies> getModuleDependencies(
StringRef moduleName, ModuleDependenciesCache &cache) override;
StringRef moduleName, ModuleDependenciesCache &cache,
SubASTContextDelegate &delegate) override;
};

/// Imports serialized Swift modules into an ASTContext.
Expand Down
5 changes: 3 additions & 2 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1462,13 +1462,14 @@ void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader,

Optional<ModuleDependencies> ASTContext::getModuleDependencies(
StringRef moduleName, bool isUnderlyingClangModule,
ModuleDependenciesCache &cache) {
ModuleDependenciesCache &cache, SubASTContextDelegate &delegate) {
for (auto &loader : getImpl().ModuleLoaders) {
if (isUnderlyingClangModule &&
loader.get() != getImpl().TheClangModuleLoader)
continue;

if (auto dependencies = loader->getModuleDependencies(moduleName, cache))
if (auto dependencies = loader->getModuleDependencies(moduleName, cache,
delegate))
return dependencies;
}

Expand Down
3 changes: 2 additions & 1 deletion lib/ClangImporter/ClangModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ static void recordModuleDependencies(
}

Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
StringRef moduleName, ModuleDependenciesCache &cache) {
StringRef moduleName, ModuleDependenciesCache &cache,
SubASTContextDelegate &delegate) {
// Check whether there is already a cached result.
if (auto found = cache.findDependencies(
moduleName, ModuleDependenciesKind::Clang))
Expand Down
85 changes: 54 additions & 31 deletions lib/Frontend/ModuleInterfaceBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#define DEBUG_TYPE "textual-module-interface"

#include "swift/Frontend/ModuleInterfaceLoader.h"
#include "ModuleInterfaceBuilder.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsFrontend.h"
Expand Down Expand Up @@ -82,19 +83,37 @@ void ModuleInterfaceBuilder::configureSubInvocationInputsAndOutputs(
.setMainAndSupplementaryOutputs({MainOut}, {SOPs});
}

void ModuleInterfaceBuilder::configureSubInvocation(
void swift::inheritOptionsForBuildingInterface(
CompilerInvocation &Invok,
const SearchPathOptions &SearchPathOpts,
const LangOptions &LangOpts,
ClangModuleLoader *ClangLoader) {
const LangOptions &LangOpts) {
// Start with a SubInvocation that copies various state from our
// invoking ASTContext.
subInvocation.setImportSearchPaths(SearchPathOpts.ImportSearchPaths);
subInvocation.setFrameworkSearchPaths(SearchPathOpts.FrameworkSearchPaths);
subInvocation.setSDKPath(SearchPathOpts.SDKPath);
subInvocation.setInputKind(InputFileKind::SwiftModuleInterface);
subInvocation.setRuntimeResourcePath(SearchPathOpts.RuntimeResourcePath);
subInvocation.setTargetTriple(LangOpts.Target);
Invok.setImportSearchPaths(SearchPathOpts.ImportSearchPaths);
Invok.setFrameworkSearchPaths(SearchPathOpts.FrameworkSearchPaths);
Invok.setSDKPath(SearchPathOpts.SDKPath);
Invok.setInputKind(InputFileKind::SwiftModuleInterface);
Invok.setRuntimeResourcePath(SearchPathOpts.RuntimeResourcePath);
Invok.setTargetTriple(LangOpts.Target);

// Inhibit warnings from the SubInvocation since we are assuming the user
// is not in a position to fix them.
Invok.getDiagnosticOptions().SuppressWarnings = true;

// Inherit this setting down so that it can affect error diagnostics (mostly
// by making them non-fatal).
Invok.getLangOptions().DebuggerSupport = LangOpts.DebuggerSupport;

// Disable this; deinitializers always get printed with `@objc` even in
// modules that don't import Foundation.
Invok.getLangOptions().EnableObjCAttrRequiresFoundation = false;
}

void ModuleInterfaceBuilder::configureSubInvocation(
const SearchPathOptions &SearchPathOpts,
const LangOptions &LangOpts,
ClangModuleLoader *ClangLoader) {
inheritOptionsForBuildingInterface(subInvocation, SearchPathOpts, LangOpts);
subInvocation.setModuleName(moduleName);
subInvocation.setClangModuleCachePath(moduleCachePath);
subInvocation.getFrontendOptions().PrebuiltModuleCachePath =
Expand All @@ -111,18 +130,6 @@ void ModuleInterfaceBuilder::configureSubInvocation(
}
}

// Inhibit warnings from the SubInvocation since we are assuming the user
// is not in a position to fix them.
subInvocation.getDiagnosticOptions().SuppressWarnings = true;

// Inherit this setting down so that it can affect error diagnostics (mostly
// by making them non-fatal).
subInvocation.getLangOptions().DebuggerSupport = LangOpts.DebuggerSupport;

// Disable this; deinitializers always get printed with `@objc` even in
// modules that don't import Foundation.
subInvocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;

// Tell the subinvocation to serialize dependency hashes if asked to do so.
auto &frontendOpts = subInvocation.getFrontendOptions();
frontendOpts.SerializeModuleInterfaceDependencyHashes =
Expand All @@ -134,35 +141,44 @@ void ModuleInterfaceBuilder::configureSubInvocation(
remarkOnRebuildFromInterface;
}

bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
swift::version::Version &Vers, StringRef &CompilerVersion,
llvm::StringSaver &SubArgSaver, SmallVectorImpl<const char *> &SubArgs) {
llvm::vfs::FileSystem &fs = *sourceMgr.getFileSystem();
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
bool swift::extractSwiftInterfaceVersionAndArgs(
SourceManager &SM,
DiagnosticEngine &Diags,
StringRef InterfacePath,
version::Version &Vers,
StringRef &CompilerVersion,
llvm::StringSaver &SubArgSaver,
SmallVectorImpl<const char *> &SubArgs,
SourceLoc diagnosticLoc) {
llvm::vfs::FileSystem &fs = *SM.getFileSystem();
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, InterfacePath);
if (!FileOrError) {
// Don't use this->diagnose() because it'll just try to re-open
// interfacePath.
diags.diagnose(diagnosticLoc, diag::error_open_input_file,
interfacePath, FileOrError.getError().message());
Diags.diagnose(diagnosticLoc, diag::error_open_input_file,
InterfacePath, FileOrError.getError().message());
return true;
}
auto SB = FileOrError.get()->getBuffer();
auto VersRe = getSwiftInterfaceFormatVersionRegex();
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
auto FlagRe = getSwiftInterfaceModuleFlagsRegex();
SmallVector<StringRef, 1> VersMatches, FlagMatches, CompMatches;

if (!VersRe.match(SB, &VersMatches)) {
diagnose(diag::error_extracting_version_from_module_interface);
ModuleInterfaceBuilder::diagnose(Diags, SM, InterfacePath, diagnosticLoc,
diag::error_extracting_version_from_module_interface);
return true;
}
if (!FlagRe.match(SB, &FlagMatches)) {
diagnose(diag::error_extracting_flags_from_module_interface);
ModuleInterfaceBuilder::diagnose(Diags, SM, InterfacePath, diagnosticLoc,
diag::error_extracting_version_from_module_interface);
return true;
}
assert(VersMatches.size() == 2);
assert(FlagMatches.size() == 2);
// FIXME We should diagnose this at a location that makes sense:
Vers = swift::version::Version(VersMatches[1], SourceLoc(), &diags);
Vers = swift::version::Version(VersMatches[1], SourceLoc(), &Diags);
llvm::cl::TokenizeGNUCommandLine(FlagMatches[1], SubArgSaver, SubArgs);

if (CompRe.match(SB, &CompMatches)) {
Expand All @@ -177,6 +193,13 @@ bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
return false;
}

bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
swift::version::Version &Vers, StringRef &CompilerVersion,
llvm::StringSaver &SubArgSaver, SmallVectorImpl<const char *> &SubArgs) {
return swift::extractSwiftInterfaceVersionAndArgs(sourceMgr, diags,
interfacePath, Vers, CompilerVersion, SubArgSaver, SubArgs, diagnosticLoc);
}

bool ModuleInterfaceBuilder::collectDepsForSerialization(
CompilerInstance &SubInstance, SmallVectorImpl<FileDependency> &Deps,
bool IsHashBased) {
Expand Down
26 changes: 20 additions & 6 deletions lib/Frontend/ModuleInterfaceBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,31 @@ class ModuleInterfaceBuilder {
CompilerInvocation subInvocation;
SmallVector<StringRef, 3> extraDependencies;

public:
/// Emit a diagnostic tied to this declaration.
template<typename ...ArgTypes>
InFlightDiagnostic diagnose(
static InFlightDiagnostic diagnose(
DiagnosticEngine &Diags,
SourceManager &SM,
StringRef InterfacePath,
SourceLoc Loc,
Diag<ArgTypes...> ID,
typename detail::PassArgument<ArgTypes>::type... Args) const {
SourceLoc loc = diagnosticLoc;
if (loc.isInvalid()) {
typename detail::PassArgument<ArgTypes>::type... Args) {
if (Loc.isInvalid()) {
// Diagnose this inside the interface file, if possible.
loc = sourceMgr.getLocFromExternalSource(interfacePath, 1, 1);
Loc = SM.getLocFromExternalSource(InterfacePath, 1, 1);
}
return diags.diagnose(loc, ID, std::move(Args)...);
return Diags.diagnose(Loc, ID, std::move(Args)...);
}

private:
/// Emit a diagnostic tied to this declaration.
template<typename ...ArgTypes>
InFlightDiagnostic diagnose(
Diag<ArgTypes...> ID,
typename detail::PassArgument<ArgTypes>::type... Args) const {
return diagnose(diags, sourceMgr, interfacePath, diagnosticLoc,
ID, std::move(Args)...);
}

void configureSubInvocationInputsAndOutputs(StringRef OutPath);
Expand Down
Loading