150 lines · cpp
1//===- unittests/Serialization/ForceCheckFileInputTest.cpp - CI tests -----===//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/ASTMatchers/ASTMatchFinder.h"10#include "clang/ASTMatchers/ASTMatchers.h"11#include "clang/Basic/FileManager.h"12#include "clang/Driver/CreateInvocationFromArgs.h"13#include "clang/Frontend/CompilerInstance.h"14#include "clang/Frontend/CompilerInvocation.h"15#include "clang/Frontend/FrontendActions.h"16#include "clang/Frontend/Utils.h"17#include "clang/Lex/HeaderSearch.h"18#include "clang/Lex/PreprocessorOptions.h"19#include "clang/Serialization/ASTReader.h"20#include "clang/Tooling/Tooling.h"21#include "llvm/ADT/SmallString.h"22#include "llvm/Support/FileSystem.h"23#include "llvm/Support/raw_ostream.h"24 25#include "gtest/gtest.h"26 27using namespace llvm;28using namespace clang;29 30namespace {31 32class ForceCheckFileInputTest : public ::testing::Test {33 void SetUp() override {34 EXPECT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir));35 }36 37 void TearDown() override { sys::fs::remove_directories(TestDir); }38 39public:40 SmallString<256> TestDir;41 42 void addFile(StringRef Path, StringRef Contents) {43 EXPECT_FALSE(sys::path::is_absolute(Path));44 45 SmallString<256> AbsPath(TestDir);46 sys::path::append(AbsPath, Path);47 48 EXPECT_FALSE(49 sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));50 51 std::error_code EC;52 llvm::raw_fd_ostream OS(AbsPath, EC);53 EXPECT_FALSE(EC);54 OS << Contents;55 }56};57 58TEST_F(ForceCheckFileInputTest, ForceCheck) {59 addFile("a.cppm", R"cpp(60export module a;61export int aa = 43;62 )cpp");63 64 std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();65 66 {67 CreateInvocationOptions CIOpts;68 CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();69 70 DiagnosticOptions DiagOpts;71 IntrusiveRefCntPtr<DiagnosticsEngine> Diags =72 CompilerInstance::createDiagnostics(*CIOpts.VFS, DiagOpts);73 CIOpts.Diags = Diags;74 75 const char *Args[] = {"clang++", "-std=c++20",76 "--precompile", "-working-directory",77 TestDir.c_str(), "a.cppm"};78 std::shared_ptr<CompilerInvocation> Invocation =79 createInvocation(Args, CIOpts);80 EXPECT_TRUE(Invocation);81 Invocation->getFrontendOpts().DisableFree = false;82 83 auto Buf = CIOpts.VFS->getBufferForFile("a.cppm");84 EXPECT_TRUE(Buf);85 86 Invocation->getPreprocessorOpts().addRemappedFile("a.cppm", Buf->get());87 88 Buf->release();89 90 CompilerInstance Instance(std::move(Invocation));91 Instance.setDiagnostics(Diags);92 93 Instance.getFrontendOpts().OutputFile = BMIPath;94 95 Instance.createVirtualFileSystem(CIOpts.VFS);96 Instance.createFileManager();97 98 Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true;99 100 GenerateReducedModuleInterfaceAction Action;101 EXPECT_TRUE(Instance.ExecuteAction(Action));102 EXPECT_FALSE(Diags->hasErrorOccurred());103 }104 105 {106 CreateInvocationOptions CIOpts;107 CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();108 DiagnosticOptions DiagOpts;109 IntrusiveRefCntPtr<DiagnosticsEngine> Diags =110 CompilerInstance::createDiagnostics(*CIOpts.VFS, DiagOpts);111 CIOpts.Diags = Diags;112 113 std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str();114 const char *Args[] = {115 "clang++", "-std=c++20", "--precompile", "-working-directory",116 TestDir.c_str(), "a.cppm", "-o", BMIPath.c_str()};117 std::shared_ptr<CompilerInvocation> Invocation =118 createInvocation(Args, CIOpts);119 EXPECT_TRUE(Invocation);120 Invocation->getFrontendOpts().DisableFree = false;121 122 CompilerInstance Clang(std::move(Invocation));123 124 Clang.setDiagnostics(Diags);125 Clang.createVirtualFileSystem(CIOpts.VFS);126 Clang.createFileManager();127 Clang.createSourceManager();128 129 EXPECT_TRUE(Clang.createTarget());130 Clang.createPreprocessor(TU_Complete);131 Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true;132 Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true;133 Clang.createASTReader();134 135 addFile("a.cppm", R"cpp(136export module a;137export int aa = 44;138 )cpp");139 140 auto ReadResult =141 Clang.getASTReader()->ReadAST(BMIPath, serialization::MK_MainFile,142 SourceLocation(), ASTReader::ARR_None);143 144 // We shall be able to detect the content change here.145 EXPECT_NE(ReadResult, ASTReader::Success);146 }147}148 149} // anonymous namespace150