llvm-project/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp
kadir çetinkaya bdd10d9d24
[NFC] Explicitly pass a VFS when creating DiagnosticsEngine (#115852)
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.
2024-11-21 12:11:41 +01:00

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