Skip to content

Commit 7150e54

Browse files
[Caching] Identify input type from filename correctly
When loading input from CAS, `swift-frontend` relies on the input file name to determine the type to look from CAS entry. In the case where file extension is `.private.swiftinterface`, swift mis-identify that as `.swiftinterface` file and look up the wrong input file. Add a new file type lookup function that can figure out the type from the full filename. Also add few diagnostics during the CAS lookup for the input file to error out immediately, rather than rely on the lookup failure later.
1 parent dfe1e69 commit 7150e54

File tree

6 files changed

+96
-7
lines changed

6 files changed

+96
-7
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,10 @@ ERROR(error_cas, none, "CAS error encountered: %0", (StringRef))
504504
ERROR(error_failed_cached_diag, none, "failed to serialize cached diagnostics: %0", (StringRef))
505505
ERROR(error_replay_cached_diag, none, "failed to replay cached diagnostics: %0", (StringRef))
506506

507+
ERROR(error_load_input_from_cas, none, "failed to load input '%0' from CAS", (StringRef))
508+
509+
ERROR(error_wrong_input_num_for_input_file_key, none, "-input-file-key only support one input file", ())
510+
507511
// Dependency Verifier Diagnostics
508512
ERROR(missing_member_dependency,none,
509513
"expected "

include/swift/Basic/FileTypes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ StringRef getExtension(ID Id);
3939
/// the invalid type \c TY_INVALID.
4040
ID lookupTypeForExtension(StringRef Ext);
4141

42+
/// Lookup the type to use for the file name \p Filename.
43+
/// If the filename is empty or type cannot be recognoized, return
44+
/// the invalid type \c TY_INVALID.
45+
ID lookupTypeFromFilename(StringRef Filename);
46+
4247
/// Lookup the type to use for the name \p Name.
4348
ID lookupTypeForName(StringRef Name);
4449

lib/Basic/FileTypes.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,29 @@ ID file_types::lookupTypeForExtension(StringRef Ext) {
5656
.Default(TY_INVALID);
5757
}
5858

59+
// Compute the file type from filename. This handles the lookup for extensions
60+
// with multiple dots, like `.private.swiftinterface` correctly.
61+
ID file_types::lookupTypeFromFilename(StringRef Filename) {
62+
StringRef MaybeExt = Filename;
63+
// Search from leftmost `.`, return the first match or till all dots are
64+
// consumed.
65+
size_t Pos = MaybeExt.find_first_of('.');
66+
while(Pos != StringRef::npos) {
67+
MaybeExt = MaybeExt.substr(Pos);
68+
// If size is 1, that means only `.` is left, return invalid.
69+
if (MaybeExt.size() == 1)
70+
return TY_INVALID;
71+
ID Type = lookupTypeForExtension(MaybeExt);
72+
if (Type != TY_INVALID)
73+
return Type;
74+
// Drop `.` and keep looking.
75+
MaybeExt = MaybeExt.drop_front();
76+
Pos = MaybeExt.find_first_of('.');
77+
}
78+
79+
return TY_INVALID;
80+
}
81+
5982
ID file_types::lookupTypeForName(StringRef Name) {
6083
return llvm::StringSwitch<file_types::ID>(Name)
6184
#define TYPE(NAME, ID, EXTENSION, FLAGS) \

lib/Frontend/Frontend.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -585,15 +585,27 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
585585
ClangOpts.BridgingHeader))
586586
MemFS->addFile(Invocation.getClangImporterOptions().BridgingHeader, 0,
587587
std::move(loadedBuffer));
588+
else
589+
Diagnostics.diagnose(
590+
SourceLoc(), diag::error_load_input_from_cas,
591+
Invocation.getClangImporterOptions().BridgingHeader);
588592
}
589593
if (!Opts.InputFileKey.empty()) {
590-
auto InputPath = Opts.InputsAndOutputs.getFilenameOfFirstInput();
591-
auto Type = file_types::lookupTypeForExtension(
592-
llvm::sys::path::extension(InputPath));
593-
if (auto loadedBuffer = loadCachedCompileResultFromCacheKey(
594-
getObjectStore(), getActionCache(), Diagnostics,
595-
Opts.InputFileKey, Type, InputPath))
596-
MemFS->addFile(InputPath, 0, std::move(loadedBuffer));
594+
if (Opts.InputsAndOutputs.getAllInputs().size() != 1)
595+
Diagnostics.diagnose(SourceLoc(),
596+
diag::error_wrong_input_num_for_input_file_key);
597+
else {
598+
auto InputPath = Opts.InputsAndOutputs.getFilenameOfFirstInput();
599+
auto Type = file_types::lookupTypeFromFilename(
600+
llvm::sys::path::filename(InputPath));
601+
if (auto loadedBuffer = loadCachedCompileResultFromCacheKey(
602+
getObjectStore(), getActionCache(), Diagnostics,
603+
Opts.InputFileKey, Type, InputPath))
604+
MemFS->addFile(InputPath, 0, std::move(loadedBuffer));
605+
else
606+
Diagnostics.diagnose(SourceLoc(), diag::error_load_input_from_cas,
607+
InputPath);
608+
}
597609
}
598610
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
599611
new llvm::vfs::OverlayFileSystem(SourceMgr.getFileSystem());

unittests/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_swift_unittest(SwiftBasicTests
1717
EncodedSequenceTest.cpp
1818
ExponentialGrowthAppendingBinaryByteStreamTests.cpp
1919
FileSystemTest.cpp
20+
FileTypes.cpp
2021
FixedBitSetTest.cpp
2122
FrozenMultiMapTest.cpp
2223
ImmutablePointerSetTest.cpp

unittests/Basic/FileTypes.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===--- FileTypes.cpp - for swift/Basic/FileTypes.h ----------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/Basic/FileTypes.h"
14+
#include "gtest/gtest.h"
15+
16+
namespace {
17+
using namespace swift;
18+
using namespace swift::file_types;
19+
20+
static const std::vector<std::pair<std::string, ID>> ExtIDs = {
21+
#define TYPE(NAME, ID, EXTENSION, FLAGS) {EXTENSION, TY_##ID},
22+
#include "swift/Basic/FileTypes.def"
23+
};
24+
25+
TEST(FileSystem, lookupTypeFromFilename) {
26+
for (auto &Entry: ExtIDs) {
27+
// no extension, skip.
28+
if (Entry.first.empty())
29+
continue;
30+
// raw-sil and raw-sib do not have unique extension.
31+
if (Entry.second == TY_RawSIL || Entry.second == TY_RawSIB)
32+
continue;
33+
34+
std::string Filename = "Myfile." + Entry.first;
35+
ID Type = lookupTypeFromFilename(Filename);
36+
ASSERT_EQ(getTypeName(Type), getTypeName(Entry.second));
37+
}
38+
39+
ASSERT_EQ(lookupTypeFromFilename(""), TY_INVALID);
40+
ASSERT_EQ(lookupTypeFromFilename("."), TY_INVALID);
41+
ASSERT_EQ(lookupTypeFromFilename(".."), TY_INVALID);
42+
}
43+
44+
} // namespace

0 commit comments

Comments
 (0)