
Starting with 41e3919ded78d8870f7c95e9181c7f7e29aa3cc4 DiagnosticsEngine creation might perform IO. It was implicitly defaulting to getRealFileSystem. This patch makes it explicit by pushing the decision making to callers. It uses ambient VFS if one is available, and keeps using `getRealFileSystem` if there aren't any VFS.
133 lines
3.9 KiB
C++
133 lines
3.9 KiB
C++
//===- unittests/Serialization/PreambleInNamedModulesTest.cpp -------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
#include "clang/Frontend/CompilerInvocation.h"
|
|
#include "clang/Frontend/FrontendActions.h"
|
|
#include "clang/Frontend/PrecompiledPreamble.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
using namespace clang;
|
|
|
|
namespace {
|
|
|
|
class PreambleInNamedModulesTest : public ::testing::Test {
|
|
void SetUp() override {
|
|
ASSERT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir));
|
|
}
|
|
|
|
void TearDown() override { sys::fs::remove_directories(TestDir); }
|
|
|
|
public:
|
|
using PathType = SmallString<256>;
|
|
|
|
PathType TestDir;
|
|
|
|
void addFile(StringRef Path, StringRef Contents, PathType &AbsPath) {
|
|
ASSERT_FALSE(sys::path::is_absolute(Path));
|
|
|
|
AbsPath = TestDir;
|
|
sys::path::append(AbsPath, Path);
|
|
|
|
ASSERT_FALSE(
|
|
sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));
|
|
|
|
std::error_code EC;
|
|
llvm::raw_fd_ostream OS(AbsPath, EC);
|
|
ASSERT_FALSE(EC);
|
|
OS << Contents;
|
|
}
|
|
|
|
void addFile(StringRef Path, StringRef Contents) {
|
|
PathType UnusedAbsPath;
|
|
addFile(Path, Contents, UnusedAbsPath);
|
|
}
|
|
};
|
|
|
|
// Testing that the use of Preamble in named modules can work basically.
|
|
// See https://github.com/llvm/llvm-project/issues/80570
|
|
TEST_F(PreambleInNamedModulesTest, BasicTest) {
|
|
addFile("foo.h", R"cpp(
|
|
enum class E {
|
|
A,
|
|
B,
|
|
C,
|
|
D
|
|
};
|
|
)cpp");
|
|
|
|
PathType MainFilePath;
|
|
addFile("A.cppm", R"cpp(
|
|
module;
|
|
#include "foo.h"
|
|
export module A;
|
|
export using ::E;
|
|
)cpp",
|
|
MainFilePath);
|
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
|
|
llvm::vfs::createPhysicalFileSystem();
|
|
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
|
|
CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions());
|
|
|
|
CreateInvocationOptions CIOpts;
|
|
CIOpts.Diags = Diags;
|
|
CIOpts.VFS = VFS;
|
|
|
|
const char *Args[] = {"clang++", "-std=c++20", "-working-directory",
|
|
TestDir.c_str(), MainFilePath.c_str()};
|
|
std::shared_ptr<CompilerInvocation> Invocation =
|
|
createInvocation(Args, CIOpts);
|
|
ASSERT_TRUE(Invocation);
|
|
|
|
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> ContentsBuffer =
|
|
llvm::MemoryBuffer::getFile(MainFilePath, /*IsText=*/true);
|
|
EXPECT_TRUE(ContentsBuffer);
|
|
std::unique_ptr<MemoryBuffer> Buffer = std::move(*ContentsBuffer);
|
|
|
|
PreambleBounds Bounds =
|
|
ComputePreambleBounds(Invocation->getLangOpts(), *Buffer, 0);
|
|
|
|
PreambleCallbacks Callbacks;
|
|
llvm::ErrorOr<PrecompiledPreamble> BuiltPreamble = PrecompiledPreamble::Build(
|
|
*Invocation, Buffer.get(), Bounds, *Diags, VFS,
|
|
std::make_shared<PCHContainerOperations>(),
|
|
/*StoreInMemory=*/false, /*StoragePath=*/TestDir, Callbacks);
|
|
|
|
ASSERT_FALSE(Diags->hasErrorOccurred());
|
|
|
|
EXPECT_TRUE(BuiltPreamble);
|
|
EXPECT_TRUE(BuiltPreamble->CanReuse(*Invocation, *Buffer, Bounds, *VFS));
|
|
BuiltPreamble->OverridePreamble(*Invocation, VFS, Buffer.get());
|
|
|
|
auto Clang = std::make_unique<CompilerInstance>(
|
|
std::make_shared<PCHContainerOperations>());
|
|
Clang->setInvocation(std::move(Invocation));
|
|
Clang->setDiagnostics(Diags.get());
|
|
|
|
if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
|
|
Clang->getInvocation(), Clang->getDiagnostics(), VFS))
|
|
VFS = VFSWithRemapping;
|
|
|
|
Clang->createFileManager(VFS);
|
|
EXPECT_TRUE(Clang->createTarget());
|
|
|
|
Buffer.release();
|
|
|
|
SyntaxOnlyAction Action;
|
|
EXPECT_TRUE(Clang->ExecuteAction(Action));
|
|
EXPECT_FALSE(Clang->getDiagnosticsPtr()->hasErrorOccurred());
|
|
}
|
|
|
|
} // namespace
|