1//===- unittests/Serialization/PreambleInNamedModulesTest.cpp -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Frontend/CompilerInstance.h"
10#include "clang/Frontend/CompilerInvocation.h"
11#include "clang/Frontend/FrontendActions.h"
12#include "clang/Frontend/PrecompiledPreamble.h"
13#include "llvm/ADT/SmallString.h"
14#include "llvm/Support/FileSystem.h"
15#include "llvm/Support/raw_ostream.h"
16
17#include "gtest/gtest.h"
18
19using namespace llvm;
20using namespace clang;
21
22namespace {
23
24class PreambleInNamedModulesTest : public ::testing::Test {
25 void SetUp() override {
26 ASSERT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir));
27 }
28
29 void TearDown() override { sys::fs::remove_directories(path: TestDir); }
30
31public:
32 using PathType = SmallString<256>;
33
34 PathType TestDir;
35
36 void addFile(StringRef Path, StringRef Contents, PathType &AbsPath) {
37 ASSERT_FALSE(sys::path::is_absolute(Path));
38
39 AbsPath = TestDir;
40 sys::path::append(path&: AbsPath, a: Path);
41
42 ASSERT_FALSE(
43 sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));
44
45 std::error_code EC;
46 llvm::raw_fd_ostream OS(AbsPath, EC);
47 ASSERT_FALSE(EC);
48 OS << Contents;
49 }
50
51 void addFile(StringRef Path, StringRef Contents) {
52 PathType UnusedAbsPath;
53 addFile(Path, Contents, AbsPath&: UnusedAbsPath);
54 }
55};
56
57// Testing that the use of Preamble in named modules can work basically.
58// See https://github.com/llvm/llvm-project/issues/80570
59TEST_F(PreambleInNamedModulesTest, BasicTest) {
60 addFile(Path: "foo.h", Contents: R"cpp(
61enum class E {
62 A,
63 B,
64 C,
65 D
66};
67 )cpp");
68
69 PathType MainFilePath;
70 addFile(Path: "A.cppm", Contents: R"cpp(
71module;
72#include "foo.h"
73export module A;
74export using ::E;
75 )cpp",
76 AbsPath&: MainFilePath);
77
78 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
79 llvm::vfs::createPhysicalFileSystem();
80 DiagnosticOptions DiagOpts;
81 IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
82 CompilerInstance::createDiagnostics(VFS&: *VFS, Opts&: DiagOpts);
83
84 CreateInvocationOptions CIOpts;
85 CIOpts.Diags = Diags;
86 CIOpts.VFS = VFS;
87
88 const char *Args[] = {"clang++", "-std=c++20", "-working-directory",
89 TestDir.c_str(), MainFilePath.c_str()};
90 std::shared_ptr<CompilerInvocation> Invocation =
91 createInvocation(Args, Opts: CIOpts);
92 ASSERT_TRUE(Invocation);
93
94 llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> ContentsBuffer =
95 llvm::MemoryBuffer::getFile(Filename: MainFilePath, /*IsText=*/true);
96 EXPECT_TRUE(ContentsBuffer);
97 std::unique_ptr<MemoryBuffer> Buffer = std::move(*ContentsBuffer);
98
99 PreambleBounds Bounds =
100 ComputePreambleBounds(LangOpts: Invocation->getLangOpts(), Buffer: *Buffer, MaxLines: 0);
101
102 PreambleCallbacks Callbacks;
103 llvm::ErrorOr<PrecompiledPreamble> BuiltPreamble = PrecompiledPreamble::Build(
104 Invocation: *Invocation, MainFileBuffer: Buffer.get(), Bounds, Diagnostics&: *Diags, VFS,
105 PCHContainerOps: std::make_shared<PCHContainerOperations>(),
106 /*StoreInMemory=*/false, /*StoragePath=*/TestDir, Callbacks);
107
108 ASSERT_FALSE(Diags->hasErrorOccurred());
109
110 EXPECT_TRUE(BuiltPreamble);
111 EXPECT_TRUE(BuiltPreamble->CanReuse(*Invocation, *Buffer, Bounds, *VFS));
112 BuiltPreamble->OverridePreamble(CI&: *Invocation, VFS, MainFileBuffer: Buffer.get());
113
114 auto Clang = std::make_unique<CompilerInstance>(args: std::move(Invocation));
115 Clang->setDiagnostics(Diags.get());
116
117 if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
118 CI: Clang->getInvocation(), Diags&: Clang->getDiagnostics(), BaseFS: VFS))
119 VFS = VFSWithRemapping;
120
121 Clang->createFileManager(VFS);
122 EXPECT_TRUE(Clang->createTarget());
123
124 Buffer.release();
125
126 SyntaxOnlyAction Action;
127 EXPECT_TRUE(Clang->ExecuteAction(Action));
128 EXPECT_FALSE(Clang->getDiagnosticsPtr()->hasErrorOccurred());
129}
130
131} // namespace
132

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/Serialization/PreambleInNamedModulesTest.cpp