145c16051SChuanqi Xu //===- unittests/Serialization/ForceCheckFileInputTest.cpp - CI tests -----===// 245c16051SChuanqi Xu // 345c16051SChuanqi Xu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 445c16051SChuanqi Xu // See https://llvm.org/LICENSE.txt for license information. 545c16051SChuanqi Xu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 645c16051SChuanqi Xu // 745c16051SChuanqi Xu //===----------------------------------------------------------------------===// 845c16051SChuanqi Xu 945c16051SChuanqi Xu #include "clang/ASTMatchers/ASTMatchFinder.h" 1045c16051SChuanqi Xu #include "clang/ASTMatchers/ASTMatchers.h" 1145c16051SChuanqi Xu #include "clang/Basic/FileManager.h" 1245c16051SChuanqi Xu #include "clang/Frontend/CompilerInstance.h" 1345c16051SChuanqi Xu #include "clang/Frontend/CompilerInvocation.h" 1445c16051SChuanqi Xu #include "clang/Frontend/FrontendActions.h" 1545c16051SChuanqi Xu #include "clang/Frontend/Utils.h" 1645c16051SChuanqi Xu #include "clang/Lex/HeaderSearch.h" 1745c16051SChuanqi Xu #include "clang/Lex/PreprocessorOptions.h" 1845c16051SChuanqi Xu #include "clang/Serialization/ASTReader.h" 1945c16051SChuanqi Xu #include "clang/Tooling/Tooling.h" 2045c16051SChuanqi Xu #include "llvm/ADT/SmallString.h" 2145c16051SChuanqi Xu #include "llvm/Support/FileSystem.h" 2245c16051SChuanqi Xu #include "llvm/Support/raw_ostream.h" 2345c16051SChuanqi Xu 2445c16051SChuanqi Xu #include "gtest/gtest.h" 2545c16051SChuanqi Xu 2645c16051SChuanqi Xu using namespace llvm; 2745c16051SChuanqi Xu using namespace clang; 2845c16051SChuanqi Xu 2945c16051SChuanqi Xu namespace { 3045c16051SChuanqi Xu 3145c16051SChuanqi Xu class ForceCheckFileInputTest : public ::testing::Test { 3245c16051SChuanqi Xu void SetUp() override { 3345c16051SChuanqi Xu EXPECT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir)); 3445c16051SChuanqi Xu } 3545c16051SChuanqi Xu 3645c16051SChuanqi Xu void TearDown() override { sys::fs::remove_directories(TestDir); } 3745c16051SChuanqi Xu 3845c16051SChuanqi Xu public: 3945c16051SChuanqi Xu SmallString<256> TestDir; 4045c16051SChuanqi Xu 4145c16051SChuanqi Xu void addFile(StringRef Path, StringRef Contents) { 4245c16051SChuanqi Xu EXPECT_FALSE(sys::path::is_absolute(Path)); 4345c16051SChuanqi Xu 4445c16051SChuanqi Xu SmallString<256> AbsPath(TestDir); 4545c16051SChuanqi Xu sys::path::append(AbsPath, Path); 4645c16051SChuanqi Xu 4745c16051SChuanqi Xu EXPECT_FALSE( 4845c16051SChuanqi Xu sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath))); 4945c16051SChuanqi Xu 5045c16051SChuanqi Xu std::error_code EC; 5145c16051SChuanqi Xu llvm::raw_fd_ostream OS(AbsPath, EC); 5245c16051SChuanqi Xu EXPECT_FALSE(EC); 5345c16051SChuanqi Xu OS << Contents; 5445c16051SChuanqi Xu } 5545c16051SChuanqi Xu }; 5645c16051SChuanqi Xu 5745c16051SChuanqi Xu TEST_F(ForceCheckFileInputTest, ForceCheck) { 5845c16051SChuanqi Xu addFile("a.cppm", R"cpp( 5945c16051SChuanqi Xu export module a; 6045c16051SChuanqi Xu export int aa = 43; 6145c16051SChuanqi Xu )cpp"); 6245c16051SChuanqi Xu 6345c16051SChuanqi Xu std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str(); 6445c16051SChuanqi Xu 6545c16051SChuanqi Xu { 66a1153cd6SSylvestre Ledru CreateInvocationOptions CIOpts; 67a1153cd6SSylvestre Ledru CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); 68bdd10d9dSkadir çetinkaya 69*df9a14d7SKadir Cetinkaya IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 70*df9a14d7SKadir Cetinkaya CompilerInstance::createDiagnostics(*CIOpts.VFS, 71*df9a14d7SKadir Cetinkaya new DiagnosticOptions()); 72*df9a14d7SKadir Cetinkaya CIOpts.Diags = Diags; 73*df9a14d7SKadir Cetinkaya 74da00c60dSChuanqi Xu const char *Args[] = {"clang++", "-std=c++20", 75da00c60dSChuanqi Xu "--precompile", "-working-directory", 76da00c60dSChuanqi Xu TestDir.c_str(), "a.cppm"}; 7745c16051SChuanqi Xu std::shared_ptr<CompilerInvocation> Invocation = 7845c16051SChuanqi Xu createInvocation(Args, CIOpts); 7945c16051SChuanqi Xu EXPECT_TRUE(Invocation); 80263fc4c7SBenjamin Kramer Invocation->getFrontendOpts().DisableFree = false; 8145c16051SChuanqi Xu 8245c16051SChuanqi Xu auto Buf = CIOpts.VFS->getBufferForFile("a.cppm"); 8345c16051SChuanqi Xu EXPECT_TRUE(Buf); 8445c16051SChuanqi Xu 8545c16051SChuanqi Xu Invocation->getPreprocessorOpts().addRemappedFile("a.cppm", Buf->get()); 8645c16051SChuanqi Xu 8745c16051SChuanqi Xu Buf->release(); 8845c16051SChuanqi Xu 8945c16051SChuanqi Xu CompilerInstance Instance; 9045c16051SChuanqi Xu Instance.setDiagnostics(Diags.get()); 9145c16051SChuanqi Xu Instance.setInvocation(Invocation); 9245c16051SChuanqi Xu 93da00c60dSChuanqi Xu Instance.getFrontendOpts().OutputFile = BMIPath; 94da00c60dSChuanqi Xu 9545c16051SChuanqi Xu if (auto VFSWithRemapping = createVFSFromCompilerInvocation( 9645c16051SChuanqi Xu Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS)) 9745c16051SChuanqi Xu CIOpts.VFS = VFSWithRemapping; 9845c16051SChuanqi Xu Instance.createFileManager(CIOpts.VFS); 9945c16051SChuanqi Xu 10045c16051SChuanqi Xu Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true; 10145c16051SChuanqi Xu 102da00c60dSChuanqi Xu GenerateReducedModuleInterfaceAction Action; 10345c16051SChuanqi Xu EXPECT_TRUE(Instance.ExecuteAction(Action)); 10445c16051SChuanqi Xu EXPECT_FALSE(Diags->hasErrorOccurred()); 10545c16051SChuanqi Xu } 10645c16051SChuanqi Xu 10745c16051SChuanqi Xu { 108a1153cd6SSylvestre Ledru CreateInvocationOptions CIOpts; 109a1153cd6SSylvestre Ledru CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); 110*df9a14d7SKadir Cetinkaya IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 111*df9a14d7SKadir Cetinkaya CompilerInstance::createDiagnostics(*CIOpts.VFS, 112*df9a14d7SKadir Cetinkaya new DiagnosticOptions()); 113*df9a14d7SKadir Cetinkaya CIOpts.Diags = Diags; 11445c16051SChuanqi Xu 11545c16051SChuanqi Xu std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str(); 11645c16051SChuanqi Xu const char *Args[] = { 11745c16051SChuanqi Xu "clang++", "-std=c++20", "--precompile", "-working-directory", 11845c16051SChuanqi Xu TestDir.c_str(), "a.cppm", "-o", BMIPath.c_str()}; 11945c16051SChuanqi Xu std::shared_ptr<CompilerInvocation> Invocation = 12045c16051SChuanqi Xu createInvocation(Args, CIOpts); 12145c16051SChuanqi Xu EXPECT_TRUE(Invocation); 122263fc4c7SBenjamin Kramer Invocation->getFrontendOpts().DisableFree = false; 12345c16051SChuanqi Xu 12445c16051SChuanqi Xu CompilerInstance Clang; 12545c16051SChuanqi Xu 12645c16051SChuanqi Xu Clang.setInvocation(Invocation); 12745c16051SChuanqi Xu Clang.setDiagnostics(Diags.get()); 12845c16051SChuanqi Xu FileManager *FM = Clang.createFileManager(CIOpts.VFS); 12945c16051SChuanqi Xu Clang.createSourceManager(*FM); 13045c16051SChuanqi Xu 13145c16051SChuanqi Xu EXPECT_TRUE(Clang.createTarget()); 13245c16051SChuanqi Xu Clang.createPreprocessor(TU_Complete); 13345c16051SChuanqi Xu Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true; 13445c16051SChuanqi Xu Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true; 13545c16051SChuanqi Xu Clang.createASTReader(); 13645c16051SChuanqi Xu 13745c16051SChuanqi Xu addFile("a.cppm", R"cpp( 13845c16051SChuanqi Xu export module a; 13945c16051SChuanqi Xu export int aa = 44; 14045c16051SChuanqi Xu )cpp"); 14145c16051SChuanqi Xu 14245c16051SChuanqi Xu auto ReadResult = 14345c16051SChuanqi Xu Clang.getASTReader()->ReadAST(BMIPath, serialization::MK_MainFile, 14445c16051SChuanqi Xu SourceLocation(), ASTReader::ARR_None); 14545c16051SChuanqi Xu 14645c16051SChuanqi Xu // We shall be able to detect the content change here. 14745c16051SChuanqi Xu EXPECT_NE(ReadResult, ASTReader::Success); 14845c16051SChuanqi Xu } 14945c16051SChuanqi Xu } 15045c16051SChuanqi Xu 15145c16051SChuanqi Xu } // anonymous namespace 152