Skip to content

Commit 2134b17

Browse files
committed
ClangImporter: Test that PCHs are actually cached in memory
Follow up 236fc19 with a ClangImporter test that we get the PCH written by this process even if it has been replaced on disk.
1 parent da8a1c5 commit 2134b17

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

unittests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ if(SWIFT_INCLUDE_TOOLS)
66

77
add_subdirectory(AST)
88
add_subdirectory(Basic)
9+
add_subdirectory(ClangImporter)
910
add_subdirectory(Driver)
1011
add_subdirectory(FrontendTool)
1112
add_subdirectory(IDE)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_swift_unittest(SwiftClangImporterTests
2+
ClangImporterTests.cpp
3+
)
4+
5+
target_link_libraries(SwiftClangImporterTests
6+
PRIVATE
7+
swiftClangImporter
8+
swiftParse
9+
swiftAST
10+
)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include "swift/AST/ASTContext.h"
2+
#include "swift/AST/DiagnosticEngine.h"
3+
#include "swift/AST/SearchPathOptions.h"
4+
#include "swift/Basic/LLVMInitialize.h"
5+
#include "swift/Basic/LangOptions.h"
6+
#include "swift/Basic/SourceManager.h"
7+
#include "swift/ClangImporter/ClangImporter.h"
8+
#include "swift/ClangImporter/ClangImporterOptions.h"
9+
#include "llvm/Support/FileSystem.h"
10+
#include "llvm/Support/Path.h"
11+
#include "llvm/Support/raw_ostream.h"
12+
#include "gtest/gtest.h"
13+
14+
using namespace swift;
15+
16+
static std::string createFilename(StringRef base, StringRef name) {
17+
SmallString<256> path = base;
18+
llvm::sys::path::append(path, name);
19+
return llvm::Twine(path).str();
20+
}
21+
22+
static bool emitFileWithContents(StringRef path, StringRef contents,
23+
std::string *pathOut = nullptr) {
24+
int FD;
25+
if (llvm::sys::fs::openFileForWrite(path, FD))
26+
return true;
27+
if (pathOut)
28+
*pathOut = path;
29+
llvm::raw_fd_ostream file(FD, /*shouldClose=*/true);
30+
file << contents;
31+
return false;
32+
}
33+
34+
static bool emitFileWithContents(StringRef base, StringRef name,
35+
StringRef contents,
36+
std::string *pathOut = nullptr) {
37+
return emitFileWithContents(createFilename(base, name), contents, pathOut);
38+
}
39+
40+
TEST(ClangImporterTest, emitPCHInMemory) {
41+
// Create a temporary cache on disk and clean it up at the end.
42+
ClangImporterOptions options;
43+
SmallString<256> temp;
44+
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory(
45+
"ClangImporterTest.emitPCHInMemory", temp));
46+
SWIFT_DEFER { llvm::sys::fs::remove_directories(temp); };
47+
48+
// Create a cache subdirectory for the modules and PCH.
49+
std::string cache = createFilename(temp, "cache");
50+
ASSERT_FALSE(llvm::sys::fs::create_directory(cache));
51+
options.ModuleCachePath = cache;
52+
options.PrecompiledHeaderOutputDir = cache;
53+
54+
// Create the includes.
55+
std::string include = createFilename(temp, "include");
56+
ASSERT_FALSE(llvm::sys::fs::create_directory(include));
57+
options.ExtraArgs.emplace_back("-nosysteminc");
58+
options.ExtraArgs.emplace_back((llvm::Twine("-I") + include).str());
59+
ASSERT_FALSE(emitFileWithContents(include, "module.modulemap",
60+
"module A {\n"
61+
" header \"A.h\"\n"
62+
"}\n"));
63+
ASSERT_FALSE(emitFileWithContents(include, "A.h", "int foo(void);\n"));
64+
65+
// Create a bridging header.
66+
ASSERT_FALSE(emitFileWithContents(temp, "bridging.h", "#import <A.h>\n",
67+
&options.BridgingHeader));
68+
69+
// Set up the importer and emit a bridging PCH.
70+
swift::LangOptions langOpts;
71+
langOpts.Target = llvm::Triple("x86_64", "apple", "darwin");
72+
INITIALIZE_LLVM();
73+
swift::SearchPathOptions searchPathOpts;
74+
swift::SourceManager sourceMgr;
75+
swift::DiagnosticEngine diags(sourceMgr);
76+
std::unique_ptr<ASTContext> context(
77+
ASTContext::get(langOpts, searchPathOpts, sourceMgr, diags));
78+
auto importer = ClangImporter::create(*context, options);
79+
80+
std::string PCH = createFilename(cache, "bridging.h.pch");
81+
ASSERT_FALSE(importer->canReadPCH(PCH));
82+
ASSERT_FALSE(importer->emitBridgingPCH(options.BridgingHeader, PCH));
83+
ASSERT_TRUE(importer->canReadPCH(PCH));
84+
85+
// Overwrite the PCH with garbage. We should still be able to read it from
86+
// the in-memory cache.
87+
ASSERT_FALSE(emitFileWithContents(PCH, "garbage"));
88+
ASSERT_TRUE(importer->canReadPCH(PCH));
89+
}

0 commit comments

Comments
 (0)