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