|  | //====-- unittests/Frontend/ReparseWorkingDirTest.cpp - FrontendAction tests =// | 
|  | // | 
|  | // 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/Basic/Diagnostic.h" | 
|  | #include "clang/Basic/FileManager.h" | 
|  | #include "clang/Frontend/ASTUnit.h" | 
|  | #include "clang/Frontend/CompilerInstance.h" | 
|  | #include "clang/Frontend/CompilerInvocation.h" | 
|  | #include "clang/Frontend/FrontendActions.h" | 
|  | #include "clang/Frontend/FrontendOptions.h" | 
|  | #include "clang/Lex/PreprocessorOptions.h" | 
|  | #include "llvm/Support/FileSystem.h" | 
|  | #include "llvm/Support/MemoryBuffer.h" | 
|  | #include "llvm/Support/Path.h" | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace clang; | 
|  |  | 
|  | namespace { | 
|  | class ReparseWorkingDirTest : public ::testing::Test { | 
|  | IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS; | 
|  | std::shared_ptr<PCHContainerOperations> PCHContainerOpts; | 
|  |  | 
|  | public: | 
|  | void SetUp() override { VFS = new vfs::InMemoryFileSystem(); } | 
|  | void TearDown() override {} | 
|  |  | 
|  | void setWorkingDirectory(StringRef Path) { | 
|  | VFS->setCurrentWorkingDirectory(Path); | 
|  | } | 
|  |  | 
|  | void AddFile(const std::string &Filename, const std::string &Contents) { | 
|  | ::time_t now; | 
|  | ::time(&now); | 
|  | VFS->addFile(Filename, now, | 
|  | MemoryBuffer::getMemBufferCopy(Contents, Filename)); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<ASTUnit> ParseAST(StringRef EntryFile) { | 
|  | PCHContainerOpts = std::make_shared<PCHContainerOperations>(); | 
|  | auto CI = std::make_shared<CompilerInvocation>(); | 
|  | CI->getFrontendOpts().Inputs.push_back(FrontendInputFile( | 
|  | EntryFile, FrontendOptions::getInputKindForExtension( | 
|  | llvm::sys::path::extension(EntryFile).substr(1)))); | 
|  |  | 
|  | CI->getHeaderSearchOpts().AddPath("headers", | 
|  | frontend::IncludeDirGroup::Quoted, | 
|  | /*isFramework*/ false, | 
|  | /*IgnoreSysRoot*/ false); | 
|  |  | 
|  | CI->getFileSystemOpts().WorkingDir = *VFS->getCurrentWorkingDirectory(); | 
|  | CI->getTargetOpts().Triple = "i386-unknown-linux-gnu"; | 
|  |  | 
|  | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( | 
|  | CompilerInstance::createDiagnostics(new DiagnosticOptions, | 
|  | new DiagnosticConsumer)); | 
|  |  | 
|  | FileManager *FileMgr = new FileManager(CI->getFileSystemOpts(), VFS); | 
|  |  | 
|  | std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation( | 
|  | CI, PCHContainerOpts, Diags, FileMgr, false, CaptureDiagsKind::None, | 
|  | /*PrecompilePreambleAfterNParses=*/1); | 
|  | return AST; | 
|  | } | 
|  |  | 
|  | bool ReparseAST(const std::unique_ptr<ASTUnit> &AST) { | 
|  | bool reparseFailed = | 
|  | AST->Reparse(PCHContainerOpts, /*RemappedFiles*/ {}, VFS); | 
|  | return !reparseFailed; | 
|  | } | 
|  | }; | 
|  |  | 
|  | TEST_F(ReparseWorkingDirTest, ReparseWorkingDir) { | 
|  | // Setup the working directory path. | 
|  | SmallString<16> WorkingDir; | 
|  | #ifdef _WIN32 | 
|  | WorkingDir = "C:\\"; | 
|  | #else | 
|  | WorkingDir = "/"; | 
|  | #endif | 
|  | llvm::sys::path::append(WorkingDir, "root"); | 
|  | setWorkingDirectory(WorkingDir); | 
|  |  | 
|  | SmallString<32> Header; | 
|  | llvm::sys::path::append(Header, WorkingDir, "headers", "header.h"); | 
|  |  | 
|  | SmallString<32> MainName; | 
|  | llvm::sys::path::append(MainName, WorkingDir, "main.cpp"); | 
|  |  | 
|  | AddFile(MainName.str().str(), R"cpp( | 
|  | #include "header.h" | 
|  | int main() { return foo(); } | 
|  | )cpp"); | 
|  | AddFile(Header.str().str(), R"h( | 
|  | static int foo() { return 0; } | 
|  | )h"); | 
|  |  | 
|  | // Parse the main file, ensuring we can include the header. | 
|  | std::unique_ptr<ASTUnit> AST(ParseAST(MainName.str())); | 
|  | ASSERT_TRUE(AST.get()); | 
|  | ASSERT_FALSE(AST->getDiagnostics().hasErrorOccurred()); | 
|  |  | 
|  | // Reparse and check that the working directory was preserved. | 
|  | ASSERT_TRUE(ReparseAST(AST)); | 
|  |  | 
|  | const auto &FM = AST->getFileManager(); | 
|  | const auto &FS = FM.getVirtualFileSystem(); | 
|  | ASSERT_EQ(FM.getFileSystemOpts().WorkingDir, WorkingDir); | 
|  | ASSERT_EQ(*FS.getCurrentWorkingDirectory(), WorkingDir); | 
|  | } | 
|  |  | 
|  | } // end anonymous namespace |