Skip to content

Commit 454ab1f

Browse files
committed
[ClangImporter] Respect -working-directory in the created VFS
Pass a wrapped VFS down into `clang::createInvocationFromCommandLine` so that the working directory is set and then used in the underlying Clang `CompilerInstance`. Fixes the possibility of differing modules hashes when the same arguments are used in Clang directly vs from the importer. Resolves rdar://79376364
1 parent d79b69b commit 454ab1f

File tree

8 files changed

+38
-23
lines changed

8 files changed

+38
-23
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ namespace llvm {
2525
class Triple;
2626
class FileCollectorBase;
2727
template<typename Fn> class function_ref;
28+
namespace vfs {
29+
class FileSystem;
30+
}
2831
}
2932

3033
namespace clang {
@@ -158,6 +161,7 @@ class ClangImporter final : public ClangModuleLoader {
158161
static std::unique_ptr<clang::CompilerInvocation>
159162
createClangInvocation(ClangImporter *importer,
160163
const ClangImporterOptions &importerOpts,
164+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
161165
ArrayRef<std::string> invocationArgStrs,
162166
std::vector<std::string> *CC1Args = nullptr);
163167
ClangImporter(const ClangImporter &) = delete;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "llvm/ADT/StringExtras.h"
6464
#include "llvm/Support/CrashRecoveryContext.h"
6565
#include "llvm/Support/FileCollector.h"
66+
#include "llvm/Support/FileSystem.h"
6667
#include "llvm/Support/Memory.h"
6768
#include "llvm/Support/Path.h"
6869
#include <algorithm>
@@ -965,11 +966,11 @@ ClangImporter::getClangArguments(ASTContext &ctx) {
965966
return invocationArgStrs;
966967
}
967968

968-
std::unique_ptr<clang::CompilerInvocation>
969-
ClangImporter::createClangInvocation(ClangImporter *importer,
970-
const ClangImporterOptions &importerOpts,
971-
ArrayRef<std::string> invocationArgStrs,
972-
std::vector<std::string> *CC1Args) {
969+
std::unique_ptr<clang::CompilerInvocation> ClangImporter::createClangInvocation(
970+
ClangImporter *importer, const ClangImporterOptions &importerOpts,
971+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
972+
ArrayRef<std::string> invocationArgStrs,
973+
std::vector<std::string> *CC1Args) {
973974
std::vector<const char *> invocationArgs;
974975
invocationArgs.reserve(invocationArgStrs.size());
975976
for (auto &argStr : invocationArgStrs)
@@ -994,7 +995,7 @@ ClangImporter::createClangInvocation(ClangImporter *importer,
994995
/*owned*/false);
995996

996997
auto CI = clang::createInvocationFromCommandLine(
997-
invocationArgs, tempClangDiags, nullptr, false, CC1Args);
998+
invocationArgs, tempClangDiags, VFS, false, CC1Args);
998999

9991000
if (!CI) {
10001001
return CI;
@@ -1010,12 +1011,12 @@ ClangImporter::createClangInvocation(ClangImporter *importer,
10101011
// to missing files and report the error that clang would throw manually.
10111012
// rdar://77516546 is tracking that the clang importer should be more
10121013
// resilient and provide a module even if there were building it.
1013-
auto VFS = clang::createVFSFromCompilerInvocation(
1014+
auto TempVFS = clang::createVFSFromCompilerInvocation(
10141015
*CI, *tempClangDiags,
1015-
importer->Impl.SwiftContext.SourceMgr.getFileSystem());
1016+
VFS ? VFS : importer->Impl.SwiftContext.SourceMgr.getFileSystem());
10161017
std::vector<std::string> FilteredModuleMapFiles;
10171018
for (auto ModuleMapFile : CI->getFrontendOpts().ModuleMapFiles) {
1018-
if (VFS->exists(ModuleMapFile)) {
1019+
if (TempVFS->exists(ModuleMapFile)) {
10191020
FilteredModuleMapFiles.push_back(ModuleMapFile);
10201021
} else {
10211022
importer->Impl.diagnose(SourceLoc(), diag::module_map_not_found,
@@ -1060,11 +1061,15 @@ ClangImporter::create(ASTContext &ctx,
10601061
}
10611062
}
10621063

1064+
// Wrap Swift's FS to allow Clang to override the working directory
1065+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
1066+
llvm::vfs::RedirectingFileSystem::create({}, true,
1067+
*ctx.SourceMgr.getFileSystem());
1068+
10631069
// Create a new Clang compiler invocation.
10641070
{
1065-
importer->Impl.Invocation = createClangInvocation(importer.get(),
1066-
importerOpts,
1067-
invocationArgStrs);
1071+
importer->Impl.Invocation = createClangInvocation(
1072+
importer.get(), importerOpts, VFS, invocationArgStrs);
10681073
if (!importer->Impl.Invocation)
10691074
return nullptr;
10701075
}
@@ -1116,11 +1121,9 @@ ClangImporter::create(ASTContext &ctx,
11161121

11171122
// Set up the file manager.
11181123
{
1119-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
1120-
clang::createVFSFromCompilerInvocation(instance.getInvocation(),
1121-
instance.getDiagnostics(),
1122-
ctx.SourceMgr.getFileSystem());
1123-
instance.createFileManager(std::move(VFS));
1124+
VFS = clang::createVFSFromCompilerInvocation(
1125+
instance.getInvocation(), instance.getDiagnostics(), std::move(VFS));
1126+
instance.createFileManager(VFS);
11241127
}
11251128

11261129
// Don't stop emitting messages if we ever can't load a module.

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ void ClangImporter::recordModuleDependencies(
215215

216216
// Ensure the arguments we collected is sufficient to create a Clang
217217
// invocation.
218-
assert(createClangInvocation(this, Opts, allArgs));
218+
assert(createClangInvocation(this, Opts, nullptr, allArgs));
219219

220220
std::vector<std::string> swiftArgs;
221221
// We are using Swift frontend mode.

test/ClangImporter/MixedSource/broken-modules.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import MissingDependencyFromSwift
1818
// CHECK-NOT: no such module 'MissingDependencyFromSwift'
1919

2020
import MissingDependencyFromClang
21-
// CHECK: {{.+}}/Inputs/broken-modules/MissingDependencyFromClang.h:1:9: error: module 'Dependency' not found
21+
// CHECK: {{.+}}{{/|\\}}Inputs{{/|\\}}broken-modules{{/|\\}}MissingDependencyFromClang.h:1:9: error: module 'Dependency' not found
2222
// CHECK: broken-modules.swift:[[@LINE-2]]:8: error: could not build Objective-C module 'MissingDependencyFromClang'
2323
// CHECK: error: no such module 'MissingDependencyFromClang'
2424

test/ClangImporter/broken-modules.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import ImportsMissingHeader
2323
// CHECK: <module-includes>:1:9: note: in file included from <module-includes>:1:
2424
// CHECK-NEXT: #import "{{.*}}ImportsMissingHeader.h"
2525

26-
// CHECK: {{.*}}/Inputs/custom-modules/ImportsMissingHeader.h:1:9: error: 'this-header-does-not-exist.h' file not found
26+
// CHECK: {{.*}}{{/|\\}}Inputs{{/|\\}}custom-modules{{/|\\}}ImportsMissingHeader.h:1:9: error: 'this-header-does-not-exist.h' file not found
2727

2828
// CHECK-INDIRECT: <module-includes>:1:9: note: in file included from <module-includes>:1:
2929
// CHECK-INDIRECT-NEXT: #import "{{.*}}ImportsMissingHeaderIndirect.h"

test/ClangImporter/non-modular-include.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: not %target-swift-frontend -enable-objc-interop -typecheck %/s -I %S/Inputs/non-modular -F %S/Inputs/non-modular 2>&1 | %FileCheck --check-prefix=CHECK -check-prefix CHECK-objc %s
33
// RUN: not %target-swift-frontend -disable-objc-interop -typecheck %/s -I %S/Inputs/non-modular -F %S/Inputs/non-modular 2>&1 | %FileCheck --check-prefix=CHECK -check-prefix CHECK-native %s
44

5-
// CHECK: {{.+}}/non-modular{{/|\\}}Foo.framework/Headers{{/|\\}}Foo.h:1:10: error: include of non-modular header inside framework module 'Foo'
5+
// CHECK: {{.+}}{{/|\\}}non-modular{{/|\\}}Foo.framework{{/|\\}}Headers{{/|\\}}Foo.h:1:10: error: include of non-modular header inside framework module 'Foo'
66
// CHECK-objc: error: could not build Objective-C module 'Foo'
77
// CHECK-native: error: could not build C module 'Foo'
88
// CHECK-NOT: error

test/ClangImporter/working-directory.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
// RUN: cd %S/Inputs/ && %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -Xcc -I -Xcc custom-modules %s -dump-clang-diagnostics 2>&1 | %FileCheck %s
1+
// RUN: %empty-directory(%t/mcp)
2+
3+
// Check that equivalent invocations result in the same module hash
4+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -Xcc -I -Xcc custom-modules -module-cache-path %t/mcp -Xcc -working-directory -Xcc %S/Inputs/ %s
5+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -Xcc -I -Xcc %S/Inputs/custom-modules -module-cache-path %t/mcp %s
6+
// RUN: find %t/mcp -name "ObjCParseExtras-*.pcm" | count 1
7+
8+
// Check that the working directory is set to the CWD if not explicitly passed
9+
// RUN: cd %S/Inputs/ && %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -Xcc -I -Xcc custom-modules %s -dump-clang-diagnostics -module-cache-path %t/mcp 2>&1 | %FileCheck %s
210

311
// REQUIRES: objc_interop
412

test/SourceKit/CursorInfo/injected_vfs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ func foo(
1010

1111
// CHECK-CMODULE: key.kind: source.lang.swift.ref.struct
1212
// CHECK-CMODULE: key.name: "StructDefinedInCModule"
13-
// CHECK-CMODULE: key.filepath: "{{.*}}/CModule{{/|\\\\}}CModule.h"
13+
// CHECK-CMODULE: key.filepath: "{{.*}}{{/|\\\\}}CModule{{/|\\\\}}CModule.h"
1414

1515
// CHECK-SWIFTMODULE-REF: key.kind: source.lang.swift.ref.struct
1616
// CHECK-SWIFTMODULE-REF: key.name: "StructDefinedInSwiftModule"

0 commit comments

Comments
 (0)